From 1b87f9312b3db51fe836e76d1c7c8aef14406ab1 Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 30 Dec 2014 03:23:09 +0800 Subject: [PATCH] RSX : add ClearColor() / ClearStencil() / ClearDepth() / ClearSurface() --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 497 ++++++++++++++------------------ rpcs3/Emu/RSX/GL/GLGSRender.h | 6 +- rpcs3/Emu/RSX/RSXThread.cpp | 174 ++++++----- rpcs3/Emu/RSX/RSXThread.h | 19 +- 4 files changed, 319 insertions(+), 377 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index a2c202f0c8..88d6029e2b 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -29,7 +29,7 @@ int last_width = 0, last_height = 0, last_depth_format = 0; GLenum g_last_gl_error = GL_NO_ERROR; void printGlError(GLenum err, const char* situation) { - if(err != GL_NO_ERROR) + if (err != GL_NO_ERROR) { LOG_ERROR(RSX, "%s: opengl error 0x%04x", situation, err); Emu.Pause(); @@ -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"); @@ -184,9 +187,9 @@ void GLTexture::Init(RSXTexture& tex) log2width = log(tex.GetWidth()) / log(2); log2height = log(tex.GetHeight()) / log(2); - for (int i = 0; iIsShown()) m_frame->Hide(); + if (m_frame->IsShown()) + { + m_frame->Hide(); + } m_ctrl = nullptr; } @@ -831,7 +829,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw) const u32 data_offset = indexed_draw ? 0 : m_draw_array_first; - for(u32 i=0; i 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); } - if(!m_vertex_data[i].addr) + if (!m_vertex_data[i].addr) { - switch(m_vertex_data[i].type) + switch (m_vertex_data[i].type) { case CELL_GCM_VERTEX_S32K: case CELL_GCM_VERTEX_S1: @@ -1000,7 +999,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw) break; case CELL_GCM_VERTEX_F: - switch(m_vertex_data[i].size) + switch (m_vertex_data[i].size) { case 1: glVertexAttrib1f(i, (GLfloat&)m_vertex_data[i].data[0]); break; case 2: glVertexAttrib2fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break; @@ -1033,9 +1032,9 @@ void GLGSRender::EnableVertexData(bool indexed_draw) void GLGSRender::DisableVertexData() { m_vdata.clear(); - for(u32 i=0; ioffset; //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); @@ -1103,13 +1102,13 @@ void GLGSRender::InitFragmentData() checkForGlError("glUniform4f " + name + fmt::Format(" %u [%f %f %f %f]", l, c.x, c.y, c.z, c.w)); } - //if(m_fragment_constants.GetCount()) + //if (m_fragment_constants.GetCount()) // LOG_NOTICE(HLE, ""); } bool GLGSRender::LoadProgram() { - if(!m_cur_shader_prog) + if (!m_cur_shader_prog) { LOG_WARNING(RSX, "LoadProgram: m_cur_shader_prog == NULL"); return false; @@ -1117,7 +1116,7 @@ bool GLGSRender::LoadProgram() m_cur_shader_prog->ctrl = m_shader_ctrl; - if(!m_cur_vertex_prog) + if (!m_cur_vertex_prog) { LOG_WARNING(RSX, "LoadProgram: m_cur_vertex_prog == NULL"); return false; @@ -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) + 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"); @@ -1142,11 +1137,9 @@ bool GLGSRender::LoadProgram() f.Write(m_shader_prog.GetShaderText()); } - if(m_vp_buf_num == -1) + 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"); @@ -1156,17 +1149,17 @@ bool GLGSRender::LoadProgram() f.Write(m_vertex_prog.shader); } - if(m_fp_buf_num != -1 && m_vp_buf_num != -1) + if (m_fp_buf_num != -1 && m_vp_buf_num != -1) { m_program.id = m_prog_buffer.GetProg(m_fp_buf_num, m_vp_buf_num); } - if(m_program.id) + if (m_program.id) { // RSX Debugger: Check if this program was modified and update it if (Ini.GSLogPrograms.GetValue()) { - for(auto& program : m_debug_programs) + for (auto& program : m_debug_programs) { if (program.id == m_program.id && program.modified) { @@ -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,10 +1508,7 @@ void GLGSRender::OnReset() { m_program.UnUse(); - //m_shader_prog.id = 0; - //m_vertex_prog.id = 0; - - if(m_vbo.IsCreated()) + if (m_vbo.IsCreated()) { m_vbo.UnBind(); m_vbo.Delete(); @@ -1534,7 +1519,7 @@ void GLGSRender::OnReset() void GLGSRender::InitDrawBuffers() { - if(!m_fbo.IsCreated() || RSXThread::m_width != last_width || RSXThread::m_height != last_height || last_depth_format != m_surface_depth_format) + if (!m_fbo.IsCreated() || RSXThread::m_width != last_width || RSXThread::m_height != last_height || last_depth_format != m_surface_depth_format) { LOG_WARNING(RSX, "New FBO (%dx%d)", RSXThread::m_width, RSXThread::m_height); last_width = RSXThread::m_width; @@ -1548,7 +1533,7 @@ void GLGSRender::InitDrawBuffers() m_rbo.Create(4 + 1); checkForGlError("m_rbo.Create"); - for(int i=0; i<4; ++i) + for (int i = 0; i < 4; ++i) { m_rbo.Bind(i); m_rbo.Storage(GL_RGBA, RSXThread::m_width, RSXThread::m_height); @@ -1557,17 +1542,8 @@ void GLGSRender::InitDrawBuffers() m_rbo.Bind(4); - switch(m_surface_depth_format) + 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)"); @@ -1584,7 +1560,7 @@ void GLGSRender::InitDrawBuffers() break; } - for(int i=0; i<4; ++i) + for (int i = 0; i < 4; ++i) { m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0 + i, m_rbo.GetId(i)); checkForGlError(fmt::Format("m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT%d)", i)); @@ -1593,20 +1569,20 @@ void GLGSRender::InitDrawBuffers() m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT, m_rbo.GetId(4)); checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT)"); - if(m_surface_depth_format == 2) + if (m_surface_depth_format == 2) { m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT, m_rbo.GetId(4)); checkForGlError("m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT)"); } } - if(!m_set_surface_clip_horizontal) + if (!m_set_surface_clip_horizontal) { m_surface_clip_x = 0; m_surface_clip_w = RSXThread::m_width; } - if(!m_set_surface_clip_vertical) + if (!m_set_surface_clip_vertical) { m_surface_clip_y = 0; m_surface_clip_h = RSXThread::m_height; @@ -1664,64 +1640,48 @@ void GLGSRender::InitDrawBuffers() } } -void GLGSRender::ExecCMD(u32 cmd) +void GLGSRender::ClearColor(u32 a, u32 r, u32 g, u32 b) +{ + 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) { - assert(cmd == NV4097_CLEAR_SURFACE); - 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"); - } - - 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); - checkForGlError("glClear"); + 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; + 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()) + if (!LoadProgram()) { LOG_ERROR(RSX, "LoadProgram failed."); Emu.Pause(); @@ -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); @@ -1756,7 +1710,7 @@ void GLGSRender::ExecCMD() Enable(m_set_line_stipple, GL_LINE_STIPPLE); Enable(m_set_polygon_stipple, GL_POLYGON_STIPPLE); - if(m_set_clip_plane) + if (m_set_clip_plane) { Enable(m_clip_plane_0, GL_CLIP_PLANE0); Enable(m_clip_plane_1, GL_CLIP_PLANE1); @@ -1806,39 +1760,39 @@ void GLGSRender::ExecCMD() checkForGlError("glScissor"); } - if(m_set_two_sided_stencil_test_enable) + if (m_set_two_sided_stencil_test_enable) { - if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) + if (m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) { glStencilOpSeparate(GL_FRONT, m_stencil_fail, m_stencil_zfail, m_stencil_zpass); checkForGlError("glStencilOpSeparate"); } - if(m_set_stencil_mask) + if (m_set_stencil_mask) { glStencilMaskSeparate(GL_FRONT, m_stencil_mask); checkForGlError("glStencilMaskSeparate"); } - if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) + if (m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) { glStencilFuncSeparate(GL_FRONT, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); checkForGlError("glStencilFuncSeparate"); } - if(m_set_back_stencil_fail && m_set_back_stencil_zfail && m_set_back_stencil_zpass) + if (m_set_back_stencil_fail && m_set_back_stencil_zfail && m_set_back_stencil_zpass) { glStencilOpSeparate(GL_BACK, m_back_stencil_fail, m_back_stencil_zfail, m_back_stencil_zpass); checkForGlError("glStencilOpSeparate(GL_BACK)"); } - if(m_set_back_stencil_mask) + if (m_set_back_stencil_mask) { glStencilMaskSeparate(GL_BACK, m_back_stencil_mask); checkForGlError("glStencilMaskSeparate(GL_BACK)"); } - if(m_set_back_stencil_func && m_set_back_stencil_func_ref && m_set_back_stencil_func_mask) + if (m_set_back_stencil_func && m_set_back_stencil_func_ref && m_set_back_stencil_func_mask) { glStencilFuncSeparate(GL_BACK, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask); checkForGlError("glStencilFuncSeparate(GL_BACK)"); @@ -1846,60 +1800,62 @@ void GLGSRender::ExecCMD() } else { - if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) + if (m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) { glStencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass); checkForGlError("glStencilOp"); } - if(m_set_stencil_mask) + if (m_set_stencil_mask) { glStencilMask(m_stencil_mask); checkForGlError("glStencilMask"); } - if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) + if (m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) { glStencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); checkForGlError("glStencilFunc"); } } - // TODO: Use other glLightModel functions? - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, m_set_two_side_light_enable ? GL_TRUE : GL_FALSE); - checkForGlError("glLightModeli"); + if (m_set_two_side_light_enable) + { + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + checkForGlError("glLightModeli"); + } - if(m_set_shade_mode) + if (m_set_shade_mode) { glShadeModel(m_shade_mode); checkForGlError("glShadeModel"); } - if(m_set_depth_mask) + if (m_set_depth_mask) { glDepthMask(m_depth_mask); checkForGlError("glDepthMask"); } - if(m_set_depth_func) + if (m_set_depth_func) { glDepthFunc(m_depth_func); checkForGlError("glDepthFunc"); } - if(m_set_depth_bounds) + if (m_set_depth_bounds) { glDepthBoundsEXT(m_depth_bounds_min, m_depth_bounds_max); checkForGlError("glDepthBounds"); } - if(m_set_clip) + if (m_set_clip) { glDepthRangef(m_clip_min, m_clip_max); checkForGlError("glDepthRangef"); } - if(m_set_line_width) + if (m_set_line_width) { glLineWidth(m_line_width); checkForGlError("glLineWidth"); @@ -1917,25 +1873,25 @@ void GLGSRender::ExecCMD() checkForGlError("glPolygonStipple"); } - if(m_set_blend_equation) + if (m_set_blend_equation) { glBlendEquationSeparate(m_blend_equation_rgb, m_blend_equation_alpha); checkForGlError("glBlendEquationSeparate"); } - if(m_set_blend_sfactor && m_set_blend_dfactor) + if (m_set_blend_sfactor && m_set_blend_dfactor) { glBlendFuncSeparate(m_blend_sfactor_rgb, m_blend_dfactor_rgb, m_blend_sfactor_alpha, m_blend_dfactor_alpha); checkForGlError("glBlendFuncSeparate"); } - if(m_set_blend_color) + if (m_set_blend_color) { glBlendColor(m_blend_color_r, m_blend_color_g, m_blend_color_b, m_blend_color_a); checkForGlError("glBlendColor"); } - if(m_set_cull_face) + if (m_set_cull_face) { glCullFace(m_cull_face); checkForGlError("glCullFace"); @@ -1947,19 +1903,19 @@ void GLGSRender::ExecCMD() checkForGlError("glFrontFace"); } - if(m_set_alpha_func && m_set_alpha_ref) + if (m_set_alpha_func && m_set_alpha_ref) { glAlphaFunc(m_alpha_func, m_alpha_ref); checkForGlError("glAlphaFunc"); } - if(m_set_fog_mode) + if (m_set_fog_mode) { glFogi(GL_FOG_MODE, m_fog_mode); checkForGlError("glFogi(GL_FOG_MODE)"); } - if(m_set_fog_params) + if (m_set_fog_params) { glFogf(GL_FOG_START, m_fog_param0); checkForGlError("glFogf(GL_FOG_START)"); @@ -1967,20 +1923,20 @@ void GLGSRender::ExecCMD() checkForGlError("glFogf(GL_FOG_END)"); } - if(m_set_restart_index) + if (m_set_restart_index) { glPrimitiveRestartIndex(m_restart_index); checkForGlError("glPrimitiveRestartIndex"); } - if(m_indexed_array.m_count && m_draw_array_count) + if (m_indexed_array.m_count && m_draw_array_count) { LOG_WARNING(RSX, "m_indexed_array.m_count && draw_array_count"); } - for(u32 i=0; i(m_gcm_buffers_addr); + u32 addr = GetAddress(buffers[m_gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL); - if (m_read_buffer) + if (Memory.IsGoodAddr(addr)) { - format = GL_BGRA; - CellGcmDisplayInfo* buffers = vm::get_ptr(m_gcm_buffers_addr); - u32 addr = GetAddress(buffers[m_gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL); - - if (Memory.IsGoodAddr(addr)) - { - width = buffers[m_gcm_current_buffer].width; - height = buffers[m_gcm_current_buffer].height; - src_buffer = vm::get_ptr(addr); - } - else - { - src_buffer = nullptr; - } - } - else if (m_fbo.IsCreated()) - { - format = GL_RGBA; - static std::vector pixels; - pixels.resize(RSXThread::m_width * RSXThread::m_height * 4); - m_fbo.Bind(GL_READ_FRAMEBUFFER); - glBindBuffer(GL_PIXEL_PACK_BUFFER, g_pbo[5]); - glBufferData(GL_PIXEL_PACK_BUFFER, RSXThread::m_width * RSXThread::m_height * 4, 0, GL_STREAM_READ); - glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 0); - checkForGlError("Flip(): glReadPixels(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8)"); - GLubyte *packed = (GLubyte *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); - if (packed) - { - memcpy(pixels.data(), packed, RSXThread::m_width * RSXThread::m_height * 4); - glUnmapBuffer(GL_PIXEL_PACK_BUFFER); - checkForGlError("Flip(): glUnmapBuffer"); - } - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - - src_buffer = pixels.data(); - width = RSXThread::m_width; - height = RSXThread::m_height; + width = buffers[m_gcm_current_buffer].width; + height = buffers[m_gcm_current_buffer].height; + src_buffer = vm::get_ptr(addr); } else - src_buffer = nullptr; - - if (src_buffer) { - glDisable(GL_STENCIL_TEST); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CLIP_PLANE0); - glDisable(GL_CLIP_PLANE1); - glDisable(GL_CLIP_PLANE2); - glDisable(GL_CLIP_PLANE3); - glDisable(GL_CLIP_PLANE4); - glDisable(GL_CLIP_PLANE5); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, g_flip_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_INT_8_8_8_8, src_buffer); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, 1, 0, 1, 0, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0); - - m_program.UnUse(); - m_program.Use(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_ACCUM_BUFFER_BIT); - - glColor3f(1, 1, 1); - 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(); + src_buffer = nullptr; } } - break; + else if (m_fbo.IsCreated()) + { + format = GL_RGBA; + static std::vector pixels; + pixels.resize(RSXThread::m_width * RSXThread::m_height * 4); + m_fbo.Bind(GL_READ_FRAMEBUFFER); + glBindBuffer(GL_PIXEL_PACK_BUFFER, g_pbo[5]); + glBufferData(GL_PIXEL_PACK_BUFFER, RSXThread::m_width * RSXThread::m_height * 4, 0, GL_STREAM_READ); + glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 0); + checkForGlError("Flip(): glReadPixels(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8)"); + GLubyte *packed = (GLubyte *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); + if (packed) + { + memcpy(pixels.data(), packed, RSXThread::m_width * RSXThread::m_height * 4); + glUnmapBuffer(GL_PIXEL_PACK_BUFFER); + checkForGlError("Flip(): glUnmapBuffer"); + } + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + + src_buffer = pixels.data(); + width = RSXThread::m_width; + height = RSXThread::m_height; + } + else + { + src_buffer = nullptr; + } + + if (src_buffer) + { + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CLIP_PLANE0); + glDisable(GL_CLIP_PLANE1); + glDisable(GL_CLIP_PLANE2); + glDisable(GL_CLIP_PLANE3); + glDisable(GL_CLIP_PLANE4); + glDisable(GL_CLIP_PLANE5); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, g_flip_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_INT_8_8_8_8, src_buffer); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, 1, 0, 1, 0, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0); + + m_program.UnUse(); + m_program.Use(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_ACCUM_BUFFER_BIT); + + glColor3f(1, 1, 1); + 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(); } // Draw Objects - for (uint i = 0; i>= 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; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index b89484fb87..779f7d27ed 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -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(); }; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index f1d98cf273..83cc338c19 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -15,34 +15,42 @@ 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; + } + 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; + } + 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; + } + 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; + } + break; } } @@ -106,13 +114,13 @@ void RSXVertexData::Reset() void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex=0) { - if(!addr) return; + if (!addr) return; const u32 tsize = GetTypeSize(); data.resize((start + count) * tsize * size); - for(u32 i=start; i(addr + baseOffset + stride * (i + baseIndex)); u8* dst = &data[i * tsize * size]; @@ -129,7 +137,7 @@ void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex=0) { const u16* c_src = (const u16*)src; u16* c_dst = (u16*)dst; - for(u32 j=0; j::make(args_addr); std::string debug = GetMethodName(cmd); debug += "("; - for(u32 i=0; i> 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; @@ -928,7 +922,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_DRAW_ARRAYS: { - for(u32 c=0; c> 24) + 1; - if(first < m_indexed_array.m_first) m_indexed_array.m_first = first; + if (first < m_indexed_array.m_first) m_indexed_array.m_first = first; - for(u32 i=first; i<_count; ++i) + for (u32 i=first; i<_count; ++i) { u32 index; switch(m_indexed_array.m_type) @@ -990,8 +984,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const break; } - if(index < m_indexed_array.index_min) m_indexed_array.index_min = index; - if(index > m_indexed_array.index_max) m_indexed_array.index_max = index; + if (index < m_indexed_array.index_min) m_indexed_array.index_min = index; + if (index > m_indexed_array.index_max) m_indexed_array.index_max = index; } m_indexed_array.m_count += _count; @@ -1130,7 +1124,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { //LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM[%d](%d)", index, count); - if(!m_cur_vertex_prog) + if (!m_cur_vertex_prog) { LOG_ERROR(RSX, "NV4097_SET_TRANSFORM_PROGRAM: m_cur_vertex_prog is null"); break; @@ -1148,7 +1142,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const // TODO: // (cmd)[1] = CELL_GCM_ENDIAN_SWAP((count) | ((registerCount) << 16)); \ - if(!m_cur_vertex_prog) + if (!m_cur_vertex_prog) { LOG_ERROR(RSX, "NV4097_SET_TRANSFORM_TIMEOUT: m_cur_vertex_prog is null"); break; @@ -1168,13 +1162,13 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_TRANSFORM_CONSTANT_LOAD: { - if((count - 1) % 4) + if ((count - 1) % 4) { LOG_ERROR(RSX, "NV4097_SET_TRANSFORM_CONSTANT_LOAD: bad count %d", count); break; } - for(u32 id = ARGS(0), i = 1; i= 2) + if (count >= 2) { m_set_stencil_func_ref = true; m_stencil_func_ref = ARGS(1); - if(count >= 3) + if (count >= 3) { m_set_stencil_func_mask = true; m_stencil_func_mask = ARGS(2); @@ -1305,12 +1299,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_set_stencil_fail = true; m_stencil_fail = ARGS(0); - if(count >= 2) + if (count >= 2) { m_set_stencil_zfail = true; m_stencil_zfail = ARGS(1); - if(count >= 3) + if (count >= 3) { m_set_stencil_zpass = true; m_stencil_zpass = ARGS(2); @@ -1331,12 +1325,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_set_back_stencil_func = true; m_back_stencil_func = ARGS(0); - if(count >= 2) + if (count >= 2) { m_set_back_stencil_func_ref = true; m_back_stencil_func_ref = ARGS(1); - if(count >= 3) + if (count >= 3) { m_set_back_stencil_func_mask = true; m_back_stencil_func_mask = ARGS(2); @@ -1364,12 +1358,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_set_stencil_fail = true; m_stencil_fail = ARGS(0); - if(count >= 2) + if (count >= 2) { m_set_back_stencil_zfail = true; m_back_stencil_zfail = ARGS(1); - if(count >= 3) + if (count >= 3) { m_set_back_stencil_zpass = true; m_back_stencil_zpass = ARGS(2); @@ -1442,7 +1436,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_scissor_x = ARGS(0) & 0xffff; m_scissor_w = ARGS(0) >> 16; - if(count == 2) + if (count == 2) { m_set_scissor_vertical = true; m_scissor_y = ARGS(1) & 0xffff; @@ -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; @@ -1600,7 +1594,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_set_context_dma_color_c = true; m_context_dma_color_c = ARGS(0); - if(count > 1) + if (count > 1) { m_set_context_dma_color_d = true; m_context_dma_color_d = ARGS(1); @@ -1650,7 +1644,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_surface_clip_x = a0; m_surface_clip_w = a0 >> 16; - if(count == 2) + if (count == 2) { const u32 a1 = ARGS(1); m_set_surface_clip_vertical = true; @@ -2058,21 +2052,21 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const c.y = (float&)a; } - if(count >= 3) + if (count >= 3) { u32 a = ARGS(2); a = a << 16 | a >> 16; c.z = (float&)a; } - if(count >= 4) + if (count >= 4) { u32 a = ARGS(3); a = a << 16 | a >> 16; c.w = (float&)a; } - if(count >= 5) + if (count >= 5) { LOG_WARNING(RSX, "NV308A_COLOR: count = %d", count); } @@ -2120,9 +2114,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const LOG_WARNING(RSX, "NV3089_IMAGE_IN_SIZE: m_dst_offset=0x%x, m_color: conv_in_h=0x%x, format_src_pitch=0x%x, conv_in_x=0x%x, conv_in_y=0x%x, conv_out_x=0x%x, conv_out_y=0x%x", m_dst_offset, m_color_conv_in_h, m_color_format_src_pitch, m_color_conv_in_x, m_color_conv_in_y, m_color_conv_out_x, m_color_conv_out_y); - for(u16 y=0; yget.read_sync(); u32 put = m_ctrl->put.read_sync(); - if(put == get || !Emu.IsRunning()) + if (put == get || !Emu.IsRunning()) { - if(put == get) + if (put == get) { - if(m_flip_status == 0) + if (m_flip_status == 0) m_sem_flip.post_and_wait(); m_sem_flush.post_and_wait(); } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + std::this_thread::sleep_for (std::chrono::milliseconds(1)); // hack 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) + if (cmd & CELL_GCM_METHOD_FLAG_JUMP) { u32 offs = cmd & 0x1fffffff; //LOG_WARNING(RSX, "rsx jump(0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", offs, m_ioAddress + get, cmd, get, put); m_ctrl->get.exchange(be_t::make(offs)); continue; } - if(cmd & CELL_GCM_METHOD_FLAG_CALL) + + 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::make(offs)); continue; } - if(cmd == CELL_GCM_METHOD_FLAG_RETURN) + + 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::make(get)); continue; } - if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT) + + 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; } - if(cmd == 0) //nop + if (cmd == 0) //nop { m_ctrl->get.atomic_op([](be_t& value) { @@ -2420,7 +2413,7 @@ void RSXThread::Task() auto args = vm::ptr::make((u32)Memory.RSXIOMem.RealAddr(get + 4)); - for(u32 i=0; i