From 23713d5dee8015a73ecab1bf944ebcab908e347c Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Fri, 27 Jan 2017 21:47:34 -0800 Subject: VideoCore: Split framebuffer regs from Regs struct --- src/video_core/regs_framebuffer.h | 282 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 src/video_core/regs_framebuffer.h (limited to 'src/video_core/regs_framebuffer.h') diff --git a/src/video_core/regs_framebuffer.h b/src/video_core/regs_framebuffer.h new file mode 100644 index 000000000..40d8aea0c --- /dev/null +++ b/src/video_core/regs_framebuffer.h @@ -0,0 +1,282 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "common/bit_field.h" +#include "common/common_funcs.h" +#include "common/common_types.h" + +namespace Pica { + +struct FramebufferRegs { + enum class LogicOp : u32 { + Clear = 0, + And = 1, + AndReverse = 2, + Copy = 3, + Set = 4, + CopyInverted = 5, + NoOp = 6, + Invert = 7, + Nand = 8, + Or = 9, + Nor = 10, + Xor = 11, + Equiv = 12, + AndInverted = 13, + OrReverse = 14, + OrInverted = 15, + }; + + enum class BlendEquation : u32 { + Add = 0, + Subtract = 1, + ReverseSubtract = 2, + Min = 3, + Max = 4, + }; + + enum class BlendFactor : u32 { + Zero = 0, + One = 1, + SourceColor = 2, + OneMinusSourceColor = 3, + DestColor = 4, + OneMinusDestColor = 5, + SourceAlpha = 6, + OneMinusSourceAlpha = 7, + DestAlpha = 8, + OneMinusDestAlpha = 9, + ConstantColor = 10, + OneMinusConstantColor = 11, + ConstantAlpha = 12, + OneMinusConstantAlpha = 13, + SourceAlphaSaturate = 14, + }; + + enum class CompareFunc : u32 { + Never = 0, + Always = 1, + Equal = 2, + NotEqual = 3, + LessThan = 4, + LessThanOrEqual = 5, + GreaterThan = 6, + GreaterThanOrEqual = 7, + }; + + enum class StencilAction : u32 { + Keep = 0, + Zero = 1, + Replace = 2, + Increment = 3, + Decrement = 4, + Invert = 5, + IncrementWrap = 6, + DecrementWrap = 7, + }; + + struct { + union { + // If false, logic blending is used + BitField<8, 1, u32> alphablend_enable; + }; + + union { + BitField<0, 8, BlendEquation> blend_equation_rgb; + BitField<8, 8, BlendEquation> blend_equation_a; + + BitField<16, 4, BlendFactor> factor_source_rgb; + BitField<20, 4, BlendFactor> factor_dest_rgb; + + BitField<24, 4, BlendFactor> factor_source_a; + BitField<28, 4, BlendFactor> factor_dest_a; + } alpha_blending; + + union { + BitField<0, 4, LogicOp> logic_op; + }; + + union { + u32 raw; + BitField<0, 8, u32> r; + BitField<8, 8, u32> g; + BitField<16, 8, u32> b; + BitField<24, 8, u32> a; + } blend_const; + + union { + BitField<0, 1, u32> enable; + BitField<4, 3, CompareFunc> func; + BitField<8, 8, u32> ref; + } alpha_test; + + struct { + union { + // Raw value of this register + u32 raw_func; + + // If true, enable stencil testing + BitField<0, 1, u32> enable; + + // Comparison operation for stencil testing + BitField<4, 3, CompareFunc> func; + + // Mask used to control writing to the stencil buffer + BitField<8, 8, u32> write_mask; + + // Value to compare against for stencil testing + BitField<16, 8, u32> reference_value; + + // Mask to apply on stencil test inputs + BitField<24, 8, u32> input_mask; + }; + + union { + // Raw value of this register + u32 raw_op; + + // Action to perform when the stencil test fails + BitField<0, 3, StencilAction> action_stencil_fail; + + // Action to perform when stencil testing passed but depth testing fails + BitField<4, 3, StencilAction> action_depth_fail; + + // Action to perform when both stencil and depth testing pass + BitField<8, 3, StencilAction> action_depth_pass; + }; + } stencil_test; + + union { + BitField<0, 1, u32> depth_test_enable; + BitField<4, 3, CompareFunc> depth_test_func; + BitField<8, 1, u32> red_enable; + BitField<9, 1, u32> green_enable; + BitField<10, 1, u32> blue_enable; + BitField<11, 1, u32> alpha_enable; + BitField<12, 1, u32> depth_write_enable; + }; + + INSERT_PADDING_WORDS(0x8); + } output_merger; + + // Components are laid out in reverse byte order, most significant bits first. + enum class ColorFormat : u32 { + RGBA8 = 0, + RGB8 = 1, + RGB5A1 = 2, + RGB565 = 3, + RGBA4 = 4, + }; + + enum class DepthFormat : u32 { + D16 = 0, + D24 = 2, + D24S8 = 3, + }; + + // Returns the number of bytes in the specified color format + static unsigned BytesPerColorPixel(ColorFormat format) { + switch (format) { + case ColorFormat::RGBA8: + return 4; + case ColorFormat::RGB8: + return 3; + case ColorFormat::RGB5A1: + case ColorFormat::RGB565: + case ColorFormat::RGBA4: + return 2; + default: + LOG_CRITICAL(HW_GPU, "Unknown color format %u", format); + UNIMPLEMENTED(); + } + } + + struct FramebufferConfig { + INSERT_PADDING_WORDS(0x3); + + union { + BitField<0, 4, u32> allow_color_write; // 0 = disable, else enable + }; + + INSERT_PADDING_WORDS(0x1); + + union { + BitField<0, 2, u32> allow_depth_stencil_write; // 0 = disable, else enable + }; + + DepthFormat depth_format; // TODO: Should be a BitField! + BitField<16, 3, ColorFormat> color_format; + + INSERT_PADDING_WORDS(0x4); + + u32 depth_buffer_address; + u32 color_buffer_address; + + union { + // Apparently, the framebuffer width is stored as expected, + // while the height is stored as the actual height minus one. + // Hence, don't access these fields directly but use the accessors + // GetWidth() and GetHeight() instead. + BitField<0, 11, u32> width; + BitField<12, 10, u32> height; + }; + + INSERT_PADDING_WORDS(0x1); + + inline PAddr GetColorBufferPhysicalAddress() const { + return color_buffer_address * 8; + } + inline PAddr GetDepthBufferPhysicalAddress() const { + return depth_buffer_address * 8; + } + + inline u32 GetWidth() const { + return width; + } + + inline u32 GetHeight() const { + return height + 1; + } + } framebuffer; + + // Returns the number of bytes in the specified depth format + static u32 BytesPerDepthPixel(DepthFormat format) { + switch (format) { + case DepthFormat::D16: + return 2; + case DepthFormat::D24: + return 3; + case DepthFormat::D24S8: + return 4; + default: + LOG_CRITICAL(HW_GPU, "Unknown depth format %u", format); + UNIMPLEMENTED(); + } + } + + // Returns the number of bits per depth component of the specified depth format + static u32 DepthBitsPerPixel(DepthFormat format) { + switch (format) { + case DepthFormat::D16: + return 16; + case DepthFormat::D24: + case DepthFormat::D24S8: + return 24; + default: + LOG_CRITICAL(HW_GPU, "Unknown depth format %u", format); + UNIMPLEMENTED(); + } + } + + INSERT_PADDING_WORDS(0x20); +}; + +static_assert(sizeof(FramebufferRegs) == 0x40 * sizeof(u32), + "FramebufferRegs struct has incorrect size"); + +} // namespace Pica -- cgit v1.2.3