VideoCore: Split framebuffer regs from Regs struct
parent
9017093f58
commit
23713d5dee
@ -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 <array>
|
||||
|
||||
#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
|
Loading…
Reference in New Issue