GPU: Implement texture window
This commit is contained in:
parent
f59d35023c
commit
bc8e035e37
|
@ -73,9 +73,11 @@ bool GPU::DoState(StateWrapper& sw)
|
||||||
sw.Do(&m_render_state.texture_y_flip);
|
sw.Do(&m_render_state.texture_y_flip);
|
||||||
sw.Do(&m_render_state.texpage_attribute);
|
sw.Do(&m_render_state.texpage_attribute);
|
||||||
sw.Do(&m_render_state.texlut_attribute);
|
sw.Do(&m_render_state.texlut_attribute);
|
||||||
|
sw.Do(&m_render_state.texture_window_value);
|
||||||
sw.Do(&m_render_state.texture_page_changed);
|
sw.Do(&m_render_state.texture_page_changed);
|
||||||
sw.Do(&m_render_state.texture_color_mode_changed);
|
sw.Do(&m_render_state.texture_color_mode_changed);
|
||||||
sw.Do(&m_render_state.transparency_mode_changed);
|
sw.Do(&m_render_state.transparency_mode_changed);
|
||||||
|
sw.Do(&m_render_state.texture_window_changed);
|
||||||
|
|
||||||
sw.Do(&m_drawing_area.left);
|
sw.Do(&m_drawing_area.left);
|
||||||
sw.Do(&m_drawing_area.top);
|
sw.Do(&m_drawing_area.top);
|
||||||
|
@ -113,6 +115,7 @@ bool GPU::DoState(StateWrapper& sw)
|
||||||
m_render_state.texture_page_changed = true;
|
m_render_state.texture_page_changed = true;
|
||||||
m_render_state.texture_color_mode_changed = true;
|
m_render_state.texture_color_mode_changed = true;
|
||||||
m_render_state.transparency_mode_changed = true;
|
m_render_state.transparency_mode_changed = true;
|
||||||
|
m_render_state.texture_window_changed = true;
|
||||||
UpdateGPUSTAT();
|
UpdateGPUSTAT();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,10 +440,7 @@ void GPU::WriteGP0(u32 value)
|
||||||
|
|
||||||
case 0xE2: // set texture window
|
case 0xE2: // set texture window
|
||||||
{
|
{
|
||||||
m_render_state.texture_window_mask_x = param & UINT32_C(0x1F);
|
m_render_state.SetTextureWindow(value);
|
||||||
m_render_state.texture_window_mask_y = (param >> 5) & UINT32_C(0x1F);
|
|
||||||
m_render_state.texture_window_offset_x = (param >> 10) & UINT32_C(0x1F);
|
|
||||||
m_render_state.texture_window_offset_y = (param >> 15) & UINT32_C(0x1F);
|
|
||||||
Log_DebugPrintf("Set texture window %02X %02X %02X %02X", m_render_state.texture_window_mask_x,
|
Log_DebugPrintf("Set texture window %02X %02X %02X %02X", m_render_state.texture_window_mask_x,
|
||||||
m_render_state.texture_window_mask_y, m_render_state.texture_window_offset_x,
|
m_render_state.texture_window_mask_y, m_render_state.texture_window_offset_x,
|
||||||
m_render_state.texture_window_offset_y);
|
m_render_state.texture_window_offset_y);
|
||||||
|
@ -895,6 +895,20 @@ void GPU::RenderState::SetFromPaletteAttribute(u16 value)
|
||||||
texture_page_changed = true;
|
texture_page_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPU::RenderState::SetTextureWindow(u32 value)
|
||||||
|
{
|
||||||
|
value &= TEXTURE_WINDOW_MASK;
|
||||||
|
if (texture_window_value == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
texture_window_mask_x = value & UINT32_C(0x1F);
|
||||||
|
texture_window_mask_y = (value >> 5) & UINT32_C(0x1F);
|
||||||
|
texture_window_offset_x = (value >> 10) & UINT32_C(0x1F);
|
||||||
|
texture_window_offset_y = (value >> 15) & UINT32_C(0x1F);
|
||||||
|
texture_window_value = value;
|
||||||
|
texture_window_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool GPU::DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride, const void* buffer, bool remove_alpha)
|
bool GPU::DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride, const void* buffer, bool remove_alpha)
|
||||||
{
|
{
|
||||||
std::vector<u32> rgba8_buf(width * height);
|
std::vector<u32> rgba8_buf(width * height);
|
||||||
|
|
|
@ -240,6 +240,7 @@ protected:
|
||||||
static constexpr u16 PAGE_ATTRIBUTE_TEXTURE_PAGE_MASK = UINT16_C(0b0000000000011111);
|
static constexpr u16 PAGE_ATTRIBUTE_TEXTURE_PAGE_MASK = UINT16_C(0b0000000000011111);
|
||||||
static constexpr u16 PAGE_ATTRIBUTE_MASK = UINT16_C(0b0000000111111111);
|
static constexpr u16 PAGE_ATTRIBUTE_MASK = UINT16_C(0b0000000111111111);
|
||||||
static constexpr u16 PALETTE_ATTRIBUTE_MASK = UINT16_C(0b0111111111111111);
|
static constexpr u16 PALETTE_ATTRIBUTE_MASK = UINT16_C(0b0111111111111111);
|
||||||
|
static constexpr u32 TEXTURE_WINDOW_MASK = UINT16_C(0b11111111111111111111);
|
||||||
|
|
||||||
// decoded values
|
// decoded values
|
||||||
u32 texture_page_x;
|
u32 texture_page_x;
|
||||||
|
@ -258,10 +259,12 @@ protected:
|
||||||
// original values
|
// original values
|
||||||
u16 texpage_attribute; // from register in rectangle modes/vertex in polygon modes
|
u16 texpage_attribute; // from register in rectangle modes/vertex in polygon modes
|
||||||
u16 texlut_attribute; // from vertex
|
u16 texlut_attribute; // from vertex
|
||||||
|
u32 texture_window_value;
|
||||||
|
|
||||||
bool texture_page_changed = false;
|
bool texture_page_changed = false;
|
||||||
bool texture_color_mode_changed = false;
|
bool texture_color_mode_changed = false;
|
||||||
bool transparency_mode_changed = false;
|
bool transparency_mode_changed = false;
|
||||||
|
bool texture_window_changed = false;
|
||||||
|
|
||||||
bool IsChanged() const { return texture_page_changed || texture_color_mode_changed || transparency_mode_changed; }
|
bool IsChanged() const { return texture_page_changed || texture_color_mode_changed || transparency_mode_changed; }
|
||||||
|
|
||||||
|
@ -274,11 +277,15 @@ protected:
|
||||||
bool IsTransparencyModeChanged() const { return transparency_mode_changed; }
|
bool IsTransparencyModeChanged() const { return transparency_mode_changed; }
|
||||||
void ClearTransparencyModeChangedFlag() { transparency_mode_changed = false; }
|
void ClearTransparencyModeChangedFlag() { transparency_mode_changed = false; }
|
||||||
|
|
||||||
|
bool IsTextureWindowChanged() const { return texture_window_changed; }
|
||||||
|
void ClearTextureWindowChangedFlag() { texture_window_changed = false; }
|
||||||
|
|
||||||
void SetFromPolygonTexcoord(u32 texcoord0, u32 texcoord1);
|
void SetFromPolygonTexcoord(u32 texcoord0, u32 texcoord1);
|
||||||
void SetFromRectangleTexcoord(u32 texcoord);
|
void SetFromRectangleTexcoord(u32 texcoord);
|
||||||
|
|
||||||
void SetFromPageAttribute(u16 value);
|
void SetFromPageAttribute(u16 value);
|
||||||
void SetFromPaletteAttribute(u16 value);
|
void SetFromPaletteAttribute(u16 value);
|
||||||
|
void SetTextureWindow(u32 value);
|
||||||
} m_render_state = {};
|
} m_render_state = {};
|
||||||
|
|
||||||
struct DrawingArea
|
struct DrawingArea
|
||||||
|
|
|
@ -46,9 +46,17 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices)
|
||||||
hw_vert.texpage = texpage;
|
hw_vert.texpage = texpage;
|
||||||
|
|
||||||
if (textured)
|
if (textured)
|
||||||
|
{
|
||||||
hw_vert.texcoord = Truncate16(m_GP0_command[buffer_pos++]);
|
hw_vert.texcoord = Truncate16(m_GP0_command[buffer_pos++]);
|
||||||
|
// auto [u, v] = HWVertex::DecodeTexcoord(hw_vert.texcoord);
|
||||||
|
// u = (u & (~(m_render_state.texture_window_mask_x * 8))) | ((m_render_state.texture_window_offset_x &
|
||||||
|
// m_render_state.texture_window_mask_x) * 8); v = (v & (~(m_render_state.texture_window_mask_y * 8))) |
|
||||||
|
// ((m_render_state.texture_window_offset_y & m_render_state.texture_window_mask_y) * 8);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
hw_vert.texcoord = 0;
|
hw_vert.texcoord = 0;
|
||||||
|
}
|
||||||
|
|
||||||
hw_vert.padding = 0;
|
hw_vert.padding = 0;
|
||||||
|
|
||||||
|
@ -258,15 +266,24 @@ uniform vec2 u_transparent_alpha;
|
||||||
in vec2 v_tex0;
|
in vec2 v_tex0;
|
||||||
flat in ivec4 v_texpage;
|
flat in ivec4 v_texpage;
|
||||||
uniform sampler2D samp0;
|
uniform sampler2D samp0;
|
||||||
|
uniform uvec4 u_texture_window;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
out vec4 o_col0;
|
out vec4 o_col0;
|
||||||
|
|
||||||
#if TEXTURED
|
#if TEXTURED
|
||||||
|
ivec2 ApplyTextureWindow(ivec2 coords)
|
||||||
|
{
|
||||||
|
uint x = (uint(coords.x) & ~(u_texture_window.x * 8u)) | ((u_texture_window.z & u_texture_window.x) * 8u);
|
||||||
|
uint y = (uint(coords.y) & ~(u_texture_window.y * 8u)) | ((u_texture_window.w & u_texture_window.y) * 8u);
|
||||||
|
return ivec2(int(x), int(y));
|
||||||
|
}
|
||||||
|
|
||||||
vec4 SampleFromVRAM(vec2 coord)
|
vec4 SampleFromVRAM(vec2 coord)
|
||||||
{
|
{
|
||||||
// from 0..1 to 0..255
|
// from 0..1 to 0..255
|
||||||
ivec2 icoord = ivec2(coord * vec2(255.0));
|
ivec2 icoord = ivec2(coord * vec2(255.0));
|
||||||
|
icoord = ApplyTextureWindow(icoord);
|
||||||
|
|
||||||
// adjust for tightly packed palette formats
|
// adjust for tightly packed palette formats
|
||||||
ivec2 index_coord = icoord;
|
ivec2 index_coord = icoord;
|
||||||
|
@ -493,7 +510,7 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)
|
||||||
const bool restart_line_strip = (rc_primitive == HWRenderBatch::Primitive::LineStrip);
|
const bool restart_line_strip = (rc_primitive == HWRenderBatch::Primitive::LineStrip);
|
||||||
const bool needs_flush =
|
const bool needs_flush =
|
||||||
!IsFlushed() && (m_render_state.IsTextureColorModeChanged() || m_render_state.IsTransparencyModeChanged() ||
|
!IsFlushed() && (m_render_state.IsTextureColorModeChanged() || m_render_state.IsTransparencyModeChanged() ||
|
||||||
buffer_overflow || rc_changed || restart_line_strip);
|
m_render_state.IsTextureWindowChanged() || buffer_overflow || rc_changed || restart_line_strip);
|
||||||
if (needs_flush)
|
if (needs_flush)
|
||||||
FlushRender();
|
FlushRender();
|
||||||
|
|
||||||
|
@ -544,5 +561,14 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)
|
||||||
m_render_state.ClearTransparencyModeChangedFlag();
|
m_render_state.ClearTransparencyModeChangedFlag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_render_state.IsTextureWindowChanged())
|
||||||
|
{
|
||||||
|
m_batch.texture_window_values[0] = m_render_state.texture_window_mask_x;
|
||||||
|
m_batch.texture_window_values[1] = m_render_state.texture_window_mask_y;
|
||||||
|
m_batch.texture_window_values[2] = m_render_state.texture_window_offset_x;
|
||||||
|
m_batch.texture_window_values[3] = m_render_state.texture_window_offset_y;
|
||||||
|
m_render_state.ClearTextureWindowChangedFlag();
|
||||||
|
}
|
||||||
|
|
||||||
LoadVertices(rc, num_vertices);
|
LoadVertices(rc, num_vertices);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ protected:
|
||||||
u32 texture_palette_x;
|
u32 texture_palette_x;
|
||||||
u32 texture_palette_y;
|
u32 texture_palette_y;
|
||||||
TransparencyMode transparency_mode;
|
TransparencyMode transparency_mode;
|
||||||
|
std::array<u8, 4> texture_window_values;
|
||||||
|
|
||||||
std::vector<HWVertex> vertices;
|
std::vector<HWVertex> vertices;
|
||||||
};
|
};
|
||||||
|
|
|
@ -358,8 +358,9 @@ bool GPU_HW_OpenGL::CompileProgram(GL::Program& prog, bool transparent, bool tex
|
||||||
|
|
||||||
if (textured)
|
if (textured)
|
||||||
{
|
{
|
||||||
|
prog.RegisterUniform("u_texture_window");
|
||||||
prog.RegisterUniform("samp0");
|
prog.RegisterUniform("samp0");
|
||||||
prog.Uniform1i(2, 0);
|
prog.Uniform1i(3, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -385,7 +386,11 @@ void GPU_HW_OpenGL::SetDrawState()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_batch.texture_enable)
|
if (m_batch.texture_enable)
|
||||||
|
{
|
||||||
|
prog.Uniform4ui(2, m_batch.texture_window_values[0], m_batch.texture_window_values[1],
|
||||||
|
m_batch.texture_window_values[2], m_batch.texture_window_values[3]);
|
||||||
m_vram_read_texture->Bind();
|
m_vram_read_texture->Bind();
|
||||||
|
}
|
||||||
|
|
||||||
if (m_last_transparency_enable != m_batch.transparency_enable ||
|
if (m_last_transparency_enable != m_batch.transparency_enable ||
|
||||||
(m_last_transparency_enable && m_last_transparency_mode != m_batch.transparency_mode))
|
(m_last_transparency_enable && m_last_transparency_mode != m_batch.transparency_mode))
|
||||||
|
|
Loading…
Reference in New Issue