mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-18 22:50:04 +00:00
20139141f7
fmt now automatically prints the numeric value of an enum class member by default, so we don't need to use casts any more. Reduces the line noise in our code a bit. Co-Authored-By: LC <712067+lioncash@users.noreply.github.com>
298 lines
7.8 KiB
C++
298 lines
7.8 KiB
C++
// 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 FragmentOperationMode : u32 {
|
|
Default = 0,
|
|
Gas = 1,
|
|
Shadow = 3,
|
|
};
|
|
|
|
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 {
|
|
BitField<0, 2, FragmentOperationMode> fragment_operation_mode;
|
|
// If false, logic blending is used
|
|
BitField<8, 1, u32> alphablend_enable;
|
|
};
|
|
|
|
union {
|
|
BitField<0, 3, BlendEquation> blend_equation_rgb;
|
|
BitField<8, 3, 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 {}", 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
|
|
};
|
|
|
|
BitField<0, 2, DepthFormat> depth_format;
|
|
|
|
BitField<16, 3, ColorFormat> color_format;
|
|
|
|
INSERT_PADDING_WORDS(0x4);
|
|
|
|
BitField<0, 28, u32> depth_buffer_address;
|
|
BitField<0, 28, 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;
|
|
}
|
|
|
|
ASSERT_MSG(false, "Unknown depth format {}", format);
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
ASSERT_MSG(false, "Unknown depth format {}", format);
|
|
}
|
|
|
|
INSERT_PADDING_WORDS(0x10); // Gas related registers
|
|
|
|
union {
|
|
BitField<0, 16, u32> constant; // float1.5.10
|
|
BitField<16, 16, u32> linear; // float1.5.10
|
|
} shadow;
|
|
|
|
INSERT_PADDING_WORDS(0xF);
|
|
};
|
|
|
|
static_assert(sizeof(FramebufferRegs) == 0x40 * sizeof(u32),
|
|
"FramebufferRegs struct has incorrect size");
|
|
|
|
} // namespace Pica
|