RSX : add ClearColor() / ClearStencil() / ClearDepth() / ClearSurface()

This commit is contained in:
raven02 2014-12-30 03:23:09 +08:00 committed by raven02
parent 325dd0308b
commit 1b87f9312b
4 changed files with 319 additions and 377 deletions

View File

@ -98,7 +98,9 @@ float GLTexture::GetMaxAniso(int aniso)
void GLTexture::Init(RSXTexture& tex)
{
if (tex.GetLocation() > 1)
{
return;
}
Bind();
@ -108,8 +110,9 @@ void GLTexture::Init(RSXTexture& tex)
LOG_ERROR(RSX, "Bad texture address=0x%x", texaddr);
return;
}
//ConLog.Warning("texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x",
//lOG_WARNING(RSX, "texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x",
// m_offset, m_width, m_height, m_maxaniso, m_mipmap, m_remap, m_zfunc, m_wraps, m_wrapt, m_wrapr, m_minlod, m_maxlod);
//TODO: safe init
checkForGlError("GLTexture::Init() -> glBindTexture");
@ -452,8 +455,7 @@ void GLTexture::Init(RSXTexture& tex)
}
break;
default: LOG_ERROR(RSX, "Init tex error: Bad tex format (0x%x | %s | 0x%x)", format,
(is_swizzled ? "swizzled" : "linear"), tex.GetFormat() & 0x40);
default: LOG_ERROR(RSX, "Init tex error: Bad tex format (0x%x | %s | 0x%x)", format, (is_swizzled ? "swizzled" : "linear"), tex.GetFormat() & 0x40);
break;
}
@ -693,8 +695,6 @@ void DrawCursorObj::Draw()
if (m_update_texture)
{
//m_update_texture = false;
glUniform2f(m_program.GetLocation("in_tc"), m_width, m_height);
checkForGlError("DrawCursorObj : glUniform2f");
if (!m_tex_id)
@ -714,8 +714,6 @@ void DrawCursorObj::Draw()
if (m_update_pos)
{
//m_update_pos = false;
glUniform4f(m_program.GetLocation("in_pos"), m_pos_x, m_pos_y, m_pos_z, 1.0f);
checkForGlError("DrawCursorObj : glUniform4f");
}
@ -727,10 +725,7 @@ void DrawCursorObj::Draw()
checkForGlError("DrawCursorObj : m_fbo.Bind(GL_READ_FRAMEBUFFER)");
GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0);
checkForGlError("DrawCursorObj : GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0)");
GLfbo::Blit(
0, 0, m_width, m_height,
0, 0, m_width, m_height,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
GLfbo::Blit(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
checkForGlError("DrawCursorObj : GLfbo::Blit");
m_fbo.Bind();
checkForGlError("DrawCursorObj : m_fbo.Bind");
@ -783,7 +778,7 @@ void DrawCursorObj::SetPosition(float x, float y, float z)
void DrawCursorObj::InitializeLocations()
{
//ConLog.Warning("tex0 location = 0x%x", m_program.GetLocation("tex0"));
//LOG_WARNING(RSX, "tex0 location = 0x%x", m_program.GetLocation("tex0"));
}
GLGSRender::GLGSRender()
@ -820,7 +815,10 @@ void GLGSRender::Close()
{
Stop();
if(m_frame->IsShown()) m_frame->Hide();
if (m_frame->IsShown())
{
m_frame->Hide();
}
m_ctrl = nullptr;
}
@ -980,7 +978,8 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
GL_FALSE,
};
if (m_vertex_data[i].type < 1 || m_vertex_data[i].type > 7) {
if (m_vertex_data[i].type < 1 || m_vertex_data[i].type > 7)
{
LOG_ERROR(RSX, "GLGSRender::EnableVertexData: Bad vertex data type (%d)!", m_vertex_data[i].type);
}
@ -1059,7 +1058,6 @@ void GLGSRender::InitVertexData()
l = m_program.GetLocation(name);
checkForGlError("glGetUniformLocation " + name);
//ConLog.Write(name + " x: %.02f y: %.02f z: %.02f w: %.02f", c.x, c.y, c.z, c.w);
glUniform4f(l, c.x, c.y, c.z, c.w);
checkForGlError("glUniform4f " + name + fmt::Format(" %d [%f %f %f %f]", l, c.x, c.y, c.z, c.w));
}
@ -1090,7 +1088,8 @@ void GLGSRender::InitFragmentData()
return;
}
for(const RSXTransformConstant& c : m_fragment_constants) {
for (const RSXTransformConstant& c : m_fragment_constants)
{
u32 id = c.id - m_cur_shader_prog->offset;
//LOG_WARNING(RSX,"fc%u[0x%x - 0x%x] = (%f, %f, %f, %f)", id, c.id, m_cur_shader_prog->offset, c.x, c.y, c.z, c.w);
@ -1126,13 +1125,9 @@ bool GLGSRender::LoadProgram()
m_fp_buf_num = m_prog_buffer.SearchFp(*m_cur_shader_prog, m_shader_prog);
m_vp_buf_num = m_prog_buffer.SearchVp(*m_cur_vertex_prog, m_vertex_prog);
//ConLog.Write("Create program");
if (m_fp_buf_num == -1)
{
LOG_WARNING(RSX, "FP not found in buffer!");
//m_shader_prog.DecompileAsync(*m_cur_shader_prog);
//m_shader_prog.Wait();
m_shader_prog.Decompile(*m_cur_shader_prog);
m_shader_prog.Compile();
checkForGlError("m_shader_prog.Compile");
@ -1145,8 +1140,6 @@ bool GLGSRender::LoadProgram()
if (m_vp_buf_num == -1)
{
LOG_WARNING(RSX, "VP not found in buffer!");
//m_vertex_prog.DecompileAsync(*m_cur_vertex_prog);
//m_vertex_prog.Wait();
m_vertex_prog.Decompile(*m_cur_vertex_prog);
m_vertex_prog.Compile();
checkForGlError("m_vertex_prog.Compile");
@ -1490,11 +1483,6 @@ void GLGSRender::OnInitThread()
#ifdef _WIN32
glSwapInterval(Ini.GSVSyncEnable.GetValue() ? 1 : 0);
// Undefined reference: glXSwapIntervalEXT
/*#else
if (GLXDrawable drawable = glXGetCurrentDrawable()){
glXSwapIntervalEXT(glXGetCurrentDisplay(), drawable, Ini.GSVSyncEnable.GetValue() ? 1 : 0);
}*/
#endif
}
@ -1520,9 +1508,6 @@ void GLGSRender::OnReset()
{
m_program.UnUse();
//m_shader_prog.id = 0;
//m_vertex_prog.id = 0;
if (m_vbo.IsCreated())
{
m_vbo.UnBind();
@ -1559,15 +1544,6 @@ void GLGSRender::InitDrawBuffers()
switch (m_surface_depth_format)
{
// case 0 found in BLJM60410-[Suzukaze no Melt - Days in the Sanctuary]
// [E : RSXThread]: Bad depth format! (0)
// [E : RSXThread]: glEnable: opengl error 0x0506
// [E : RSXThread]: glDrawArrays: opengl error 0x0506
case 0:
m_rbo.Storage(GL_DEPTH_COMPONENT, RSXThread::m_width, RSXThread::m_height);
checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT)");
break;
case CELL_GCM_SURFACE_Z16:
m_rbo.Storage(GL_DEPTH_COMPONENT16, RSXThread::m_width, RSXThread::m_height);
checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT16)");
@ -1664,63 +1640,47 @@ void GLGSRender::InitDrawBuffers()
}
}
void GLGSRender::ExecCMD(u32 cmd)
void GLGSRender::ClearColor(u32 a, u32 r, u32 g, u32 b)
{
assert(cmd == NV4097_CLEAR_SURFACE);
glClearColor(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
checkForGlError("glClearColor");
}
void GLGSRender::ClearStencil(u32 stencil)
{
glClearStencil(stencil);
checkForGlError("glClearStencil");
}
void GLGSRender::ClearDepth(u32 depth)
{
glClearDepth(depth / (float)0xffffff);
checkForGlError("glClearDepth");
}
void GLGSRender::ClearSurface(u32 mask)
{
InitDrawBuffers();
if(m_set_color_mask)
{
glColorMask(m_color_mask_r, m_color_mask_g, m_color_mask_b, m_color_mask_a);
checkForGlError("glColorMask");
}
GLbitfield clearMask = 0;
if (mask & 0x01) clearMask |= GL_DEPTH_BUFFER_BIT;
if (mask & 0x02) clearMask |= GL_STENCIL_BUFFER_BIT;
if (mask & 0xF0) clearMask |= GL_COLOR_BUFFER_BIT;
if (m_set_scissor_horizontal && m_set_scissor_vertical)
{
glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h);
checkForGlError("glScissor");
}
GLbitfield f = 0;
if (m_clear_surface_mask & 0x1)
{
glClearDepth(m_clear_surface_z / (float)0xffffff);
checkForGlError("glClearDepth");
f |= GL_DEPTH_BUFFER_BIT;
}
if (m_clear_surface_mask & 0x2)
{
glClearStencil(m_clear_surface_s);
checkForGlError("glClearStencil");
f |= GL_STENCIL_BUFFER_BIT;
}
if (m_clear_surface_mask & 0xF0)
{
glClearColor(
m_clear_surface_color_r / 255.0f,
m_clear_surface_color_g / 255.0f,
m_clear_surface_color_b / 255.0f,
m_clear_surface_color_a / 255.0f);
checkForGlError("glClearColor");
f |= GL_COLOR_BUFFER_BIT;
}
glClear(f);
glClear(clearMask);
checkForGlError("glClear");
WriteBuffers();
}
void GLGSRender::ColorMask(bool a, bool r, bool g, bool b)
{
glColorMask(r, g, b, a);
checkForGlError("glColorMask");
}
void GLGSRender::ExecCMD()
{
//return;
if (!LoadProgram())
{
LOG_ERROR(RSX, "LoadProgram failed.");
@ -1730,12 +1690,6 @@ void GLGSRender::ExecCMD()
InitDrawBuffers();
if (m_set_color_mask)
{
glColorMask(m_color_mask_r, m_color_mask_g, m_color_mask_b, m_color_mask_a);
checkForGlError("glColorMask");
}
Enable(m_set_depth_test, GL_DEPTH_TEST);
Enable(m_set_alpha_test, GL_ALPHA_TEST);
Enable(m_set_depth_bounds_test, GL_DEPTH_BOUNDS_TEST_EXT);
@ -1865,9 +1819,11 @@ void GLGSRender::ExecCMD()
}
}
// TODO: Use other glLightModel functions?
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, m_set_two_side_light_enable ? GL_TRUE : GL_FALSE);
if (m_set_two_side_light_enable)
{
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
checkForGlError("glLightModeli");
}
if (m_set_shade_mode)
{
@ -2007,6 +1963,7 @@ void GLGSRender::ExecCMD()
}
m_vao.Bind();
if (m_indexed_array.m_count)
{
LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1);
@ -2056,31 +2013,12 @@ void GLGSRender::ExecCMD()
void GLGSRender::Flip()
{
// Set scissor to FBO size
if (m_set_scissor_horizontal && m_set_scissor_vertical)
{
glScissor(0, 0, RSXThread::m_width, RSXThread::m_height);
checkForGlError("glScissor");
}
switch (m_surface_color_target)
{
case CELL_GCM_SURFACE_TARGET_0:
case CELL_GCM_SURFACE_TARGET_1:
case CELL_GCM_SURFACE_TARGET_MRT1:
case CELL_GCM_SURFACE_TARGET_MRT2:
case CELL_GCM_SURFACE_TARGET_MRT3:
{
// Fast path for non-MRT using glBlitFramebuffer.
GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0);
// Renderbuffer is upside turn , swapped srcY0 and srcY1
GLfbo::Blit(0, RSXThread::m_height, RSXThread::m_width, 0, 0, 0, RSXThread::m_width, RSXThread::m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
break;
case CELL_GCM_SURFACE_TARGET_NONE:
{
// Slow path for MRT/None target using glReadPixels.
static u8* src_buffer = nullptr;
static u32 width = 0;
static u32 height = 0;
@ -2127,7 +2065,9 @@ void GLGSRender::Flip()
height = RSXThread::m_height;
}
else
{
src_buffer = nullptr;
}
if (src_buffer)
{
@ -2162,20 +2102,14 @@ void GLGSRender::Flip()
glBegin(GL_QUADS);
glTexCoord2i(0, 1);
glVertex2i(0, 0);
glTexCoord2i(1, 1);
glVertex2i(1, 0);
glTexCoord2i(1, 0);
glVertex2i(1, 1);
glTexCoord2i(0, 0);
glVertex2i(0, 1);
glEnd();
}
}
break;
}
// Draw Objects
for (uint i = 0; i < m_post_draw_objs.size(); ++i)
@ -2199,19 +2133,22 @@ u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height,
u32 offset = 0;
u32 shift_count = 0;
while (log2_width | log2_height | log2_depth){
if(log2_width){
if (log2_width)
{
offset |= (x & 0x01) << shift_count;
x >>= 1;
++shift_count;
--log2_width;
}
if(log2_height){
if (log2_height)
{
offset |= (y & 0x01) << shift_count;
y >>= 1;
++shift_count;
--log2_height;
}
if(log2_depth){
if (log2_depth)
{
offset |= (z & 0x01) << shift_count;
z >>= 1;
++shift_count;

View File

@ -190,7 +190,11 @@ protected:
virtual void OnInitThread();
virtual void OnExitThread();
virtual void OnReset();
virtual void ExecCMD(u32 cmd);
virtual void ExecCMD();
virtual void ClearColor(u32 a, u32 r, u32 g, u32 b);
virtual void ClearStencil(u32 stencil);
virtual void ClearDepth(u32 depth);
virtual void ClearSurface(u32 mask);
virtual void ColorMask(bool a, bool r, bool g, bool b);
virtual void Flip();
};

View File

@ -15,33 +15,41 @@
u32 methodRegisters[0xffff];
void RSXThread::nativeRescale(float width, float height)
void RSXThread::NativeRescale(float width, float height)
{
switch (Ini.GSResolution.GetValue())
{
case 1: // 1920x1080 window size
{
m_width_scale = 1920 / width * 2.0f;
m_height_scale = 1080 / height * 2.0f;
m_width = 1920;
m_height = 1080;
}
break;
case 2: // 1280x720 window size
{
m_width_scale = 1280 / width * 2.0f;
m_height_scale = 720 / height * 2.0f;
m_width = 1280;
m_height = 720;
}
break;
case 4: // 720x480 window size
{
m_width_scale = 720 / width * 2.0f;
m_height_scale = 480 / height * 2.0f;
m_width = 720;
m_height = 480;
}
break;
case 5: // 720x576 window size
{
m_width_scale = 720 / width * 2.0f;
m_height_scale = 576 / height * 2.0f;
m_width = 720;
m_height = 576;
}
break;
}
}
@ -532,13 +540,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
// Color Mask
case NV4097_SET_COLOR_MASK:
{
const u32 a0 = ARGS(0);
m_set_color_mask = true;
m_color_mask_a = a0 & 0x1000000 ? true : false;
m_color_mask_r = a0 & 0x0010000 ? true : false;
m_color_mask_g = a0 & 0x0000100 ? true : false;
m_color_mask_b = a0 & 0x0000001 ? true : false;
const u32 mask = ARGS(0);
ColorMask(mask & 0x1000000, mask & 0x1000000, mask & 0x1000000, mask & 0x0000001);
}
break;
@ -866,35 +869,26 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_CLEAR_SURFACE:
{
const u32 a0 = ARGS(0);
const u32 mask = ARGS(0);
if(a0 & 0x01) m_clear_surface_z = m_clear_z;
if(a0 & 0x02) m_clear_surface_s = m_clear_s;
if(a0 & 0x10) m_clear_surface_color_r = m_clear_color_r;
if(a0 & 0x20) m_clear_surface_color_g = m_clear_color_g;
if(a0 & 0x40) m_clear_surface_color_b = m_clear_color_b;
if(a0 & 0x80) m_clear_surface_color_a = m_clear_color_a;
m_clear_surface_mask = a0;
ExecCMD(NV4097_CLEAR_SURFACE);
ClearSurface(mask);
}
break;
case NV4097_SET_ZSTENCIL_CLEAR_VALUE:
{
const u32 a0 = ARGS(0);
m_clear_s = a0 & 0xff;
m_clear_z = a0 >> 8;
const u32 value = ARGS(0);
ClearStencil(value & 0xff);
ClearDepth(value >> 8);
}
break;
case NV4097_SET_COLOR_CLEAR_VALUE:
{
const u32 color = ARGS(0);
m_clear_color_a = (color >> 24) & 0xff;
m_clear_color_r = (color >> 16) & 0xff;
m_clear_color_g = (color >> 8) & 0xff;
m_clear_color_b = color & 0xff;
ClearColor((color >> 24) & 0xff, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
}
break;
@ -1484,7 +1478,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
m_width = buffers[m_gcm_current_buffer].width;
m_height = buffers[m_gcm_current_buffer].height;
nativeRescale((float)m_width, (float)m_height);
NativeRescale((float)m_width, (float)m_height);
}
break;
@ -2280,18 +2274,18 @@ void RSXThread::End()
ExecCMD();
for (auto &vdata : m_vertex_data)
{
vdata.data.clear();
}
m_indexed_array.Reset();
m_fragment_constants.clear();
m_transform_constants.clear();
m_cur_shader_prog_num = 0;
//m_cur_shader_prog = nullptr;
m_clear_surface_mask = 0;
m_begin_end = 0;
//Reset();
OnReset();
}
@ -2368,15 +2362,13 @@ void RSXThread::Task()
continue;
}
//ConLog.Write("addr = 0x%x", m_ioAddress + get);
const u32 cmd = ReadIO32(get);
const u32 count = (cmd >> 18) & 0x7ff;
//if(cmd == 0) continue;
if (Ini.RSXLogging.GetValue())
{
LOG_NOTICE(Log::RSX, "%s (cmd=0x%x)", GetMethodName(cmd & 0xffff).c_str(), cmd);
//LOG_NOTICE(Log::RSX, "put=0x%x, get=0x%x, cmd=0x%x (%s)", put, get, cmd, GetMethodName(cmd & 0xffff).c_str());
}
if (cmd & CELL_GCM_METHOD_FLAG_JUMP)
{
@ -2385,27 +2377,28 @@ void RSXThread::Task()
m_ctrl->get.exchange(be_t<u32>::make(offs));
continue;
}
if (cmd & CELL_GCM_METHOD_FLAG_CALL)
{
m_call_stack.push(get + 4);
u32 offs = cmd & ~3;
//u32 addr = offs;
//LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x", offs, cmd, get);
m_ctrl->get.exchange(be_t<u32>::make(offs));
continue;
}
if (cmd == CELL_GCM_METHOD_FLAG_RETURN)
{
//LOG_WARNING(RSX, "rsx return!");
u32 get = m_call_stack.top();
m_call_stack.pop();
//LOG_WARNING(RSX, "rsx return(0x%x)", get);
m_ctrl->get.exchange(be_t<u32>::make(get));
continue;
}
if (cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
{
//LOG_WARNING(RSX, "non increment cmd! 0x%x", cmd);
//LOG_WARNING(RSX, "rsx non increment cmd! 0x%x", cmd);
inc = 0;
}
@ -2431,13 +2424,14 @@ void RSXThread::Task()
{
value += (count + 1) * 4;
});
//memset(Memory.GetMemFromAddr(p.m_ioAddress + get), 0, (count + 1) * 4);
}
catch (const std::string& e)
{
LOG_ERROR(RSX, "Exception: %s", e.c_str());
Emu.Pause();
}
catch (const char* e)
{
LOG_ERROR(RSX, "Exception: %s", e);

View File

@ -519,7 +519,10 @@ protected:
m_line_stipple_factor = 1;
m_vertex_data_base_offset = 0;
m_vertex_data_base_index = 0;
for (size_t i = 0; i < 32; i++) {
// Construct Stipple Pattern
for (size_t i = 0; i < 32; i++)
{
m_polygon_stipple_pattern[i] = 0xFFFFFFFF;
}
@ -622,14 +625,18 @@ protected:
u32 OutOfArgsCount(const uint x, const u32 cmd, const u32 count, const u32 args_addr);
void DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u32 count);
void nativeRescale(float width, float height);
void NativeRescale(float width, float height);
virtual void OnInit() = 0;
virtual void OnInitThread() = 0;
virtual void OnExitThread() = 0;
virtual void OnReset() = 0;
virtual void ExecCMD() = 0;
virtual void ExecCMD(u32 cmd) = 0;
virtual void ClearColor(u32 a, u32 r, u32 g, u32 b) = 0;
virtual void ClearStencil(u32 stencil) = 0;
virtual void ClearDepth(u32 depth) = 0;
virtual void ClearSurface(u32 mask) = 0;
virtual void ColorMask(bool a, bool r, bool g, bool b) = 0;
virtual void Flip() = 0;
void LoadVertexData(u32 first, u32 count)