summaryrefslogtreecommitdiffstats
path: root/src/video_core/regs_framebuffer.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/regs_framebuffer.h284
1 files changed, 284 insertions, 0 deletions
diff --git a/src/video_core/regs_framebuffer.h b/src/video_core/regs_framebuffer.h
new file mode 100644
index 000000000..366782080
--- /dev/null
+++ b/src/video_core/regs_framebuffer.h
@@ -0,0 +1,284 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+
+#include "common/assert.h"
+#include "common/bit_field.h"
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+#include "common/logging/log.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