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

@ -29,7 +29,7 @@ int last_width = 0, last_height = 0, last_depth_format = 0;
GLenum g_last_gl_error = GL_NO_ERROR; GLenum g_last_gl_error = GL_NO_ERROR;
void printGlError(GLenum err, const char* situation) 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); LOG_ERROR(RSX, "%s: opengl error 0x%04x", situation, err);
Emu.Pause(); Emu.Pause();
@ -98,7 +98,9 @@ float GLTexture::GetMaxAniso(int aniso)
void GLTexture::Init(RSXTexture& tex) void GLTexture::Init(RSXTexture& tex)
{ {
if (tex.GetLocation() > 1) if (tex.GetLocation() > 1)
{
return; return;
}
Bind(); Bind();
@ -108,8 +110,9 @@ void GLTexture::Init(RSXTexture& tex)
LOG_ERROR(RSX, "Bad texture address=0x%x", texaddr); LOG_ERROR(RSX, "Bad texture address=0x%x", texaddr);
return; 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); // 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 //TODO: safe init
checkForGlError("GLTexture::Init() -> glBindTexture"); checkForGlError("GLTexture::Init() -> glBindTexture");
@ -184,9 +187,9 @@ void GLTexture::Init(RSXTexture& tex)
log2width = log(tex.GetWidth()) / log(2); log2width = log(tex.GetWidth()) / log(2);
log2height = log(tex.GetHeight()) / log(2); log2height = log(tex.GetHeight()) / log(2);
for (int i = 0; i<tex.GetHeight(); i++) for (int i = 0; i < tex.GetHeight(); i++)
{ {
for (int j = 0; j<tex.GetWidth(); j++) for (int j = 0; j < tex.GetWidth(); j++)
{ {
dst[(i*tex.GetHeight()) + j] = src[LinearToSwizzleAddress(j, i, 0, log2width, log2height, 0)]; dst[(i*tex.GetHeight()) + j] = src[LinearToSwizzleAddress(j, i, 0, log2width, log2height, 0)];
} }
@ -452,8 +455,7 @@ void GLTexture::Init(RSXTexture& tex)
} }
break; break;
default: LOG_ERROR(RSX, "Init tex error: Bad tex format (0x%x | %s | 0x%x)", format, default: LOG_ERROR(RSX, "Init tex error: Bad tex format (0x%x | %s | 0x%x)", format, (is_swizzled ? "swizzled" : "linear"), tex.GetFormat() & 0x40);
(is_swizzled ? "swizzled" : "linear"), tex.GetFormat() & 0x40);
break; break;
} }
@ -693,8 +695,6 @@ void DrawCursorObj::Draw()
if (m_update_texture) if (m_update_texture)
{ {
//m_update_texture = false;
glUniform2f(m_program.GetLocation("in_tc"), m_width, m_height); glUniform2f(m_program.GetLocation("in_tc"), m_width, m_height);
checkForGlError("DrawCursorObj : glUniform2f"); checkForGlError("DrawCursorObj : glUniform2f");
if (!m_tex_id) if (!m_tex_id)
@ -714,8 +714,6 @@ void DrawCursorObj::Draw()
if (m_update_pos) 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); glUniform4f(m_program.GetLocation("in_pos"), m_pos_x, m_pos_y, m_pos_z, 1.0f);
checkForGlError("DrawCursorObj : glUniform4f"); checkForGlError("DrawCursorObj : glUniform4f");
} }
@ -727,10 +725,7 @@ void DrawCursorObj::Draw()
checkForGlError("DrawCursorObj : m_fbo.Bind(GL_READ_FRAMEBUFFER)"); checkForGlError("DrawCursorObj : m_fbo.Bind(GL_READ_FRAMEBUFFER)");
GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0); GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0);
checkForGlError("DrawCursorObj : GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0)"); checkForGlError("DrawCursorObj : GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0)");
GLfbo::Blit( GLfbo::Blit(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
0, 0, m_width, m_height,
0, 0, m_width, m_height,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
checkForGlError("DrawCursorObj : GLfbo::Blit"); checkForGlError("DrawCursorObj : GLfbo::Blit");
m_fbo.Bind(); m_fbo.Bind();
checkForGlError("DrawCursorObj : m_fbo.Bind"); checkForGlError("DrawCursorObj : m_fbo.Bind");
@ -783,7 +778,7 @@ void DrawCursorObj::SetPosition(float x, float y, float z)
void DrawCursorObj::InitializeLocations() 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() GLGSRender::GLGSRender()
@ -804,7 +799,7 @@ GLGSRender::~GLGSRender()
void GLGSRender::Enable(bool enable, const u32 cap) void GLGSRender::Enable(bool enable, const u32 cap)
{ {
if(enable) if (enable)
{ {
glEnable(cap); glEnable(cap);
} }
@ -820,7 +815,10 @@ void GLGSRender::Close()
{ {
Stop(); Stop();
if(m_frame->IsShown()) m_frame->Hide(); if (m_frame->IsShown())
{
m_frame->Hide();
}
m_ctrl = nullptr; m_ctrl = nullptr;
} }
@ -831,7 +829,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
const u32 data_offset = indexed_draw ? 0 : m_draw_array_first; const u32 data_offset = indexed_draw ? 0 : m_draw_array_first;
for(u32 i=0; i<m_vertex_count; ++i) for (u32 i = 0; i < m_vertex_count; ++i)
{ {
if (0) if (0)
{ {
@ -880,7 +878,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
m_vbo.Bind(0); m_vbo.Bind(0);
m_vbo.SetData(m_vdata.data(), m_vdata.size()); m_vbo.SetData(m_vdata.data(), m_vdata.size());
if(indexed_draw) if (indexed_draw)
{ {
m_vbo.Bind(GL_ELEMENT_ARRAY_BUFFER, 1); m_vbo.Bind(GL_ELEMENT_ARRAY_BUFFER, 1);
m_vbo.SetData(GL_ELEMENT_ARRAY_BUFFER, m_indexed_array.m_data.data(), m_indexed_array.m_data.size()); m_vbo.SetData(GL_ELEMENT_ARRAY_BUFFER, m_indexed_array.m_data.data(), m_indexed_array.m_data.size());
@ -892,61 +890,61 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
rFile dump("VertexDataArray.dump", rFile::write); rFile dump("VertexDataArray.dump", rFile::write);
#endif #endif
for(u32 i=0; i<m_vertex_count; ++i) for (u32 i = 0; i < m_vertex_count; ++i)
{ {
if(!m_vertex_data[i].IsEnabled()) continue; if (!m_vertex_data[i].IsEnabled()) continue;
#if DUMP_VERTEX_DATA #if DUMP_VERTEX_DATA
dump.Write(wxString::Format("VertexData[%d]:\n", i)); dump.Write(wxString::Format("VertexData[%d]:\n", i));
switch(m_vertex_data[i].type) switch (m_vertex_data[i].type)
{ {
case CELL_GCM_VERTEX_S1: case CELL_GCM_VERTEX_S1:
for(u32 j = 0; j<m_vertex_data[i].data.size(); j+=2) for (u32 j = 0; j < m_vertex_data[i].data.size(); j+=2)
{ {
dump.Write(wxString::Format("%d\n", *(u16*)&m_vertex_data[i].data[j])); dump.Write(wxString::Format("%d\n", *(u16*)&m_vertex_data[i].data[j]));
if(!(((j+2) / 2) % m_vertex_data[i].size)) dump.Write("\n"); if (!(((j+2) / 2) % m_vertex_data[i].size)) dump.Write("\n");
} }
break; break;
case CELL_GCM_VERTEX_F: case CELL_GCM_VERTEX_F:
for(u32 j = 0; j<m_vertex_data[i].data.size(); j+=4) for (u32 j = 0; j < m_vertex_data[i].data.size(); j+=4)
{ {
dump.Write(wxString::Format("%.01f\n", *(float*)&m_vertex_data[i].data[j])); dump.Write(wxString::Format("%.01f\n", *(float*)&m_vertex_data[i].data[j]));
if(!(((j+4) / 4) % m_vertex_data[i].size)) dump.Write("\n"); if (!(((j+4) / 4) % m_vertex_data[i].size)) dump.Write("\n");
} }
break; break;
case CELL_GCM_VERTEX_SF: case CELL_GCM_VERTEX_SF:
for(u32 j = 0; j<m_vertex_data[i].data.size(); j+=2) for (u32 j = 0; j < m_vertex_data[i].data.size(); j+=2)
{ {
dump.Write(wxString::Format("%.01f\n", *(float*)&m_vertex_data[i].data[j])); dump.Write(wxString::Format("%.01f\n", *(float*)&m_vertex_data[i].data[j]));
if(!(((j+2) / 2) % m_vertex_data[i].size)) dump.Write("\n"); if (!(((j+2) / 2) % m_vertex_data[i].size)) dump.Write("\n");
} }
break; break;
case CELL_GCM_VERTEX_UB: case CELL_GCM_VERTEX_UB:
for(u32 j = 0; j<m_vertex_data[i].data.size(); ++j) for (u32 j = 0; j < m_vertex_data[i].data.size(); ++j)
{ {
dump.Write(wxString::Format("%d\n", m_vertex_data[i].data[j])); dump.Write(wxString::Format("%d\n", m_vertex_data[i].data[j]));
if(!((j+1) % m_vertex_data[i].size)) dump.Write("\n"); if (!((j+1) % m_vertex_data[i].size)) dump.Write("\n");
} }
break; break;
case CELL_GCM_VERTEX_S32K: case CELL_GCM_VERTEX_S32K:
for(u32 j = 0; j<m_vertex_data[i].data.size(); j+=2) for (u32 j = 0; j < m_vertex_data[i].data.size(); j+=2)
{ {
dump.Write(wxString::Format("%d\n", *(u16*)&m_vertex_data[i].data[j])); dump.Write(wxString::Format("%d\n", *(u16*)&m_vertex_data[i].data[j]));
if(!(((j+2) / 2) % m_vertex_data[i].size)) dump.Write("\n"); if (!(((j+2) / 2) % m_vertex_data[i].size)) dump.Write("\n");
} }
break; break;
// case CELL_GCM_VERTEX_CMP: // case CELL_GCM_VERTEX_CMP:
case CELL_GCM_VERTEX_UB256: case CELL_GCM_VERTEX_UB256:
for(u32 j = 0; j<m_vertex_data[i].data.size(); ++j) for (u32 j = 0; j < m_vertex_data[i].data.size(); ++j)
{ {
dump.Write(wxString::Format("%d\n", m_vertex_data[i].data[j])); dump.Write(wxString::Format("%d\n", m_vertex_data[i].data[j]));
if(!((j+1) % m_vertex_data[i].size)) dump.Write("\n"); if (!((j+1) % m_vertex_data[i].size)) dump.Write("\n");
} }
break; break;
@ -980,13 +978,14 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
GL_FALSE, 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); 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_S32K:
case CELL_GCM_VERTEX_S1: case CELL_GCM_VERTEX_S1:
@ -1000,7 +999,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
break; break;
case CELL_GCM_VERTEX_F: 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 1: glVertexAttrib1f(i, (GLfloat&)m_vertex_data[i].data[0]); break;
case 2: glVertexAttrib2fv(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() void GLGSRender::DisableVertexData()
{ {
m_vdata.clear(); m_vdata.clear();
for(u32 i=0; i<m_vertex_count; ++i) for (u32 i = 0; i < m_vertex_count; ++i)
{ {
if(!m_vertex_data[i].IsEnabled()) continue; if (!m_vertex_data[i].IsEnabled()) continue;
glDisableVertexAttribArray(i); glDisableVertexAttribArray(i);
checkForGlError("glDisableVertexAttribArray"); checkForGlError("glDisableVertexAttribArray");
} }
@ -1059,7 +1058,6 @@ void GLGSRender::InitVertexData()
l = m_program.GetLocation(name); l = m_program.GetLocation(name);
checkForGlError("glGetUniformLocation " + 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); 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)); checkForGlError("glUniform4f " + name + fmt::Format(" %d [%f %f %f %f]", l, c.x, c.y, c.z, c.w));
} }
@ -1084,13 +1082,14 @@ void GLGSRender::InitVertexData()
void GLGSRender::InitFragmentData() void GLGSRender::InitFragmentData()
{ {
if(!m_cur_shader_prog) if (!m_cur_shader_prog)
{ {
LOG_ERROR(RSX, "InitFragmentData: m_cur_shader_prog == NULL"); LOG_ERROR(RSX, "InitFragmentData: m_cur_shader_prog == NULL");
return; return;
} }
for(const RSXTransformConstant& c : m_fragment_constants) { for (const RSXTransformConstant& c : m_fragment_constants)
{
u32 id = c.id - m_cur_shader_prog->offset; 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); //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)); 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, ""); // LOG_NOTICE(HLE, "");
} }
bool GLGSRender::LoadProgram() bool GLGSRender::LoadProgram()
{ {
if(!m_cur_shader_prog) if (!m_cur_shader_prog)
{ {
LOG_WARNING(RSX, "LoadProgram: m_cur_shader_prog == NULL"); LOG_WARNING(RSX, "LoadProgram: m_cur_shader_prog == NULL");
return false; return false;
@ -1117,7 +1116,7 @@ bool GLGSRender::LoadProgram()
m_cur_shader_prog->ctrl = m_shader_ctrl; 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"); LOG_WARNING(RSX, "LoadProgram: m_cur_vertex_prog == NULL");
return false; 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_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); 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!"); 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.Decompile(*m_cur_shader_prog);
m_shader_prog.Compile(); m_shader_prog.Compile();
checkForGlError("m_shader_prog.Compile"); checkForGlError("m_shader_prog.Compile");
@ -1142,11 +1137,9 @@ bool GLGSRender::LoadProgram()
f.Write(m_shader_prog.GetShaderText()); 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!"); 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.Decompile(*m_cur_vertex_prog);
m_vertex_prog.Compile(); m_vertex_prog.Compile();
checkForGlError("m_vertex_prog.Compile"); checkForGlError("m_vertex_prog.Compile");
@ -1156,17 +1149,17 @@ bool GLGSRender::LoadProgram()
f.Write(m_vertex_prog.shader); 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); 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 // RSX Debugger: Check if this program was modified and update it
if (Ini.GSLogPrograms.GetValue()) if (Ini.GSLogPrograms.GetValue())
{ {
for(auto& program : m_debug_programs) for (auto& program : m_debug_programs)
{ {
if (program.id == m_program.id && program.modified) if (program.id == m_program.id && program.modified)
{ {
@ -1490,11 +1483,6 @@ void GLGSRender::OnInitThread()
#ifdef _WIN32 #ifdef _WIN32
glSwapInterval(Ini.GSVSyncEnable.GetValue() ? 1 : 0); glSwapInterval(Ini.GSVSyncEnable.GetValue() ? 1 : 0);
// Undefined reference: glXSwapIntervalEXT
/*#else
if (GLXDrawable drawable = glXGetCurrentDrawable()){
glXSwapIntervalEXT(glXGetCurrentDisplay(), drawable, Ini.GSVSyncEnable.GetValue() ? 1 : 0);
}*/
#endif #endif
} }
@ -1520,10 +1508,7 @@ void GLGSRender::OnReset()
{ {
m_program.UnUse(); m_program.UnUse();
//m_shader_prog.id = 0; if (m_vbo.IsCreated())
//m_vertex_prog.id = 0;
if(m_vbo.IsCreated())
{ {
m_vbo.UnBind(); m_vbo.UnBind();
m_vbo.Delete(); m_vbo.Delete();
@ -1534,7 +1519,7 @@ void GLGSRender::OnReset()
void GLGSRender::InitDrawBuffers() 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); LOG_WARNING(RSX, "New FBO (%dx%d)", RSXThread::m_width, RSXThread::m_height);
last_width = RSXThread::m_width; last_width = RSXThread::m_width;
@ -1548,7 +1533,7 @@ void GLGSRender::InitDrawBuffers()
m_rbo.Create(4 + 1); m_rbo.Create(4 + 1);
checkForGlError("m_rbo.Create"); checkForGlError("m_rbo.Create");
for(int i=0; i<4; ++i) for (int i = 0; i < 4; ++i)
{ {
m_rbo.Bind(i); m_rbo.Bind(i);
m_rbo.Storage(GL_RGBA, RSXThread::m_width, RSXThread::m_height); m_rbo.Storage(GL_RGBA, RSXThread::m_width, RSXThread::m_height);
@ -1557,17 +1542,8 @@ void GLGSRender::InitDrawBuffers()
m_rbo.Bind(4); 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: case CELL_GCM_SURFACE_Z16:
m_rbo.Storage(GL_DEPTH_COMPONENT16, RSXThread::m_width, RSXThread::m_height); m_rbo.Storage(GL_DEPTH_COMPONENT16, RSXThread::m_width, RSXThread::m_height);
checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT16)"); checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT16)");
@ -1584,7 +1560,7 @@ void GLGSRender::InitDrawBuffers()
break; 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)); m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0 + i, m_rbo.GetId(i));
checkForGlError(fmt::Format("m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT%d)", 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)); m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT, m_rbo.GetId(4));
checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT)"); 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)); m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT, m_rbo.GetId(4));
checkForGlError("m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT)"); 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_x = 0;
m_surface_clip_w = RSXThread::m_width; 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_y = 0;
m_surface_clip_h = RSXThread::m_height; 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(); InitDrawBuffers();
if(m_set_color_mask) GLbitfield clearMask = 0;
{ if (mask & 0x01) clearMask |= GL_DEPTH_BUFFER_BIT;
glColorMask(m_color_mask_r, m_color_mask_g, m_color_mask_b, m_color_mask_a); if (mask & 0x02) clearMask |= GL_STENCIL_BUFFER_BIT;
checkForGlError("glColorMask"); 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);
checkForGlError("glClear");
glClear(clearMask);
checkForGlError("glClear");
WriteBuffers(); WriteBuffers();
} }
void GLGSRender::ColorMask(bool a, bool r, bool g, bool b)
{
glColorMask(r, g, b, a);
checkForGlError("glColorMask");
}
void GLGSRender::ExecCMD() void GLGSRender::ExecCMD()
{ {
//return; if (!LoadProgram())
if(!LoadProgram())
{ {
LOG_ERROR(RSX, "LoadProgram failed."); LOG_ERROR(RSX, "LoadProgram failed.");
Emu.Pause(); Emu.Pause();
@ -1730,12 +1690,6 @@ void GLGSRender::ExecCMD()
InitDrawBuffers(); 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_depth_test, GL_DEPTH_TEST);
Enable(m_set_alpha_test, GL_ALPHA_TEST); Enable(m_set_alpha_test, GL_ALPHA_TEST);
Enable(m_set_depth_bounds_test, GL_DEPTH_BOUNDS_TEST_EXT); 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_line_stipple, GL_LINE_STIPPLE);
Enable(m_set_polygon_stipple, GL_POLYGON_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_0, GL_CLIP_PLANE0);
Enable(m_clip_plane_1, GL_CLIP_PLANE1); Enable(m_clip_plane_1, GL_CLIP_PLANE1);
@ -1806,39 +1760,39 @@ void GLGSRender::ExecCMD()
checkForGlError("glScissor"); 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); glStencilOpSeparate(GL_FRONT, m_stencil_fail, m_stencil_zfail, m_stencil_zpass);
checkForGlError("glStencilOpSeparate"); checkForGlError("glStencilOpSeparate");
} }
if(m_set_stencil_mask) if (m_set_stencil_mask)
{ {
glStencilMaskSeparate(GL_FRONT, m_stencil_mask); glStencilMaskSeparate(GL_FRONT, m_stencil_mask);
checkForGlError("glStencilMaskSeparate"); 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); glStencilFuncSeparate(GL_FRONT, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask);
checkForGlError("glStencilFuncSeparate"); 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); glStencilOpSeparate(GL_BACK, m_back_stencil_fail, m_back_stencil_zfail, m_back_stencil_zpass);
checkForGlError("glStencilOpSeparate(GL_BACK)"); checkForGlError("glStencilOpSeparate(GL_BACK)");
} }
if(m_set_back_stencil_mask) if (m_set_back_stencil_mask)
{ {
glStencilMaskSeparate(GL_BACK, m_back_stencil_mask); glStencilMaskSeparate(GL_BACK, m_back_stencil_mask);
checkForGlError("glStencilMaskSeparate(GL_BACK)"); 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); glStencilFuncSeparate(GL_BACK, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask);
checkForGlError("glStencilFuncSeparate(GL_BACK)"); checkForGlError("glStencilFuncSeparate(GL_BACK)");
@ -1846,60 +1800,62 @@ void GLGSRender::ExecCMD()
} }
else 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); glStencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass);
checkForGlError("glStencilOp"); checkForGlError("glStencilOp");
} }
if(m_set_stencil_mask) if (m_set_stencil_mask)
{ {
glStencilMask(m_stencil_mask); glStencilMask(m_stencil_mask);
checkForGlError("glStencilMask"); 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); glStencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask);
checkForGlError("glStencilFunc"); checkForGlError("glStencilFunc");
} }
} }
// TODO: Use other glLightModel functions? if (m_set_two_side_light_enable)
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, m_set_two_side_light_enable ? GL_TRUE : GL_FALSE); {
checkForGlError("glLightModeli"); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
checkForGlError("glLightModeli");
}
if(m_set_shade_mode) if (m_set_shade_mode)
{ {
glShadeModel(m_shade_mode); glShadeModel(m_shade_mode);
checkForGlError("glShadeModel"); checkForGlError("glShadeModel");
} }
if(m_set_depth_mask) if (m_set_depth_mask)
{ {
glDepthMask(m_depth_mask); glDepthMask(m_depth_mask);
checkForGlError("glDepthMask"); checkForGlError("glDepthMask");
} }
if(m_set_depth_func) if (m_set_depth_func)
{ {
glDepthFunc(m_depth_func); glDepthFunc(m_depth_func);
checkForGlError("glDepthFunc"); checkForGlError("glDepthFunc");
} }
if(m_set_depth_bounds) if (m_set_depth_bounds)
{ {
glDepthBoundsEXT(m_depth_bounds_min, m_depth_bounds_max); glDepthBoundsEXT(m_depth_bounds_min, m_depth_bounds_max);
checkForGlError("glDepthBounds"); checkForGlError("glDepthBounds");
} }
if(m_set_clip) if (m_set_clip)
{ {
glDepthRangef(m_clip_min, m_clip_max); glDepthRangef(m_clip_min, m_clip_max);
checkForGlError("glDepthRangef"); checkForGlError("glDepthRangef");
} }
if(m_set_line_width) if (m_set_line_width)
{ {
glLineWidth(m_line_width); glLineWidth(m_line_width);
checkForGlError("glLineWidth"); checkForGlError("glLineWidth");
@ -1917,25 +1873,25 @@ void GLGSRender::ExecCMD()
checkForGlError("glPolygonStipple"); checkForGlError("glPolygonStipple");
} }
if(m_set_blend_equation) if (m_set_blend_equation)
{ {
glBlendEquationSeparate(m_blend_equation_rgb, m_blend_equation_alpha); glBlendEquationSeparate(m_blend_equation_rgb, m_blend_equation_alpha);
checkForGlError("glBlendEquationSeparate"); 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); glBlendFuncSeparate(m_blend_sfactor_rgb, m_blend_dfactor_rgb, m_blend_sfactor_alpha, m_blend_dfactor_alpha);
checkForGlError("glBlendFuncSeparate"); 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); glBlendColor(m_blend_color_r, m_blend_color_g, m_blend_color_b, m_blend_color_a);
checkForGlError("glBlendColor"); checkForGlError("glBlendColor");
} }
if(m_set_cull_face) if (m_set_cull_face)
{ {
glCullFace(m_cull_face); glCullFace(m_cull_face);
checkForGlError("glCullFace"); checkForGlError("glCullFace");
@ -1947,19 +1903,19 @@ void GLGSRender::ExecCMD()
checkForGlError("glFrontFace"); 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); glAlphaFunc(m_alpha_func, m_alpha_ref);
checkForGlError("glAlphaFunc"); checkForGlError("glAlphaFunc");
} }
if(m_set_fog_mode) if (m_set_fog_mode)
{ {
glFogi(GL_FOG_MODE, m_fog_mode); glFogi(GL_FOG_MODE, m_fog_mode);
checkForGlError("glFogi(GL_FOG_MODE)"); checkForGlError("glFogi(GL_FOG_MODE)");
} }
if(m_set_fog_params) if (m_set_fog_params)
{ {
glFogf(GL_FOG_START, m_fog_param0); glFogf(GL_FOG_START, m_fog_param0);
checkForGlError("glFogf(GL_FOG_START)"); checkForGlError("glFogf(GL_FOG_START)");
@ -1967,20 +1923,20 @@ void GLGSRender::ExecCMD()
checkForGlError("glFogf(GL_FOG_END)"); checkForGlError("glFogf(GL_FOG_END)");
} }
if(m_set_restart_index) if (m_set_restart_index)
{ {
glPrimitiveRestartIndex(m_restart_index); glPrimitiveRestartIndex(m_restart_index);
checkForGlError("glPrimitiveRestartIndex"); 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"); LOG_WARNING(RSX, "m_indexed_array.m_count && draw_array_count");
} }
for(u32 i=0; i<m_textures_count; ++i) for (u32 i=0; i < m_textures_count; ++i)
{ {
if(!m_textures[i].IsEnabled()) continue; if (!m_textures[i].IsEnabled()) continue;
glActiveTexture(GL_TEXTURE0 + i); glActiveTexture(GL_TEXTURE0 + i);
checkForGlError("glActiveTexture"); checkForGlError("glActiveTexture");
@ -2007,7 +1963,8 @@ void GLGSRender::ExecCMD()
} }
m_vao.Bind(); m_vao.Bind();
if(m_indexed_array.m_count)
if (m_indexed_array.m_count)
{ {
LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1); LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1);
} }
@ -2020,7 +1977,7 @@ void GLGSRender::ExecCMD()
InitFragmentData(); InitFragmentData();
} }
if(m_indexed_array.m_count) if (m_indexed_array.m_count)
{ {
switch(m_indexed_array.m_type) switch(m_indexed_array.m_type)
{ {
@ -2043,7 +2000,7 @@ void GLGSRender::ExecCMD()
m_indexed_array.Reset(); m_indexed_array.Reset();
} }
if(m_draw_array_count) if (m_draw_array_count)
{ {
//LOG_WARNING(RSX,"glDrawArrays(%d,%d,%d)", m_draw_mode - 1, m_draw_array_first, m_draw_array_count); //LOG_WARNING(RSX,"glDrawArrays(%d,%d,%d)", m_draw_mode - 1, m_draw_array_first, m_draw_array_count);
glDrawArrays(m_draw_mode - 1, 0, m_draw_array_count); glDrawArrays(m_draw_mode - 1, 0, m_draw_array_count);
@ -2056,129 +2013,106 @@ void GLGSRender::ExecCMD()
void GLGSRender::Flip() void GLGSRender::Flip()
{ {
// Set scissor to FBO size
if (m_set_scissor_horizontal && m_set_scissor_vertical) if (m_set_scissor_horizontal && m_set_scissor_vertical)
{ {
glScissor(0, 0, RSXThread::m_width, RSXThread::m_height); glScissor(0, 0, RSXThread::m_width, RSXThread::m_height);
checkForGlError("glScissor"); checkForGlError("glScissor");
} }
switch (m_surface_color_target) static u8* src_buffer = nullptr;
{ static u32 width = 0;
case CELL_GCM_SURFACE_TARGET_0: static u32 height = 0;
case CELL_GCM_SURFACE_TARGET_1: GLenum format = GL_RGBA;
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: if (m_read_buffer)
{ {
// Slow path for MRT/None target using glReadPixels. format = GL_BGRA;
static u8* src_buffer = nullptr; CellGcmDisplayInfo* buffers = vm::get_ptr<CellGcmDisplayInfo>(m_gcm_buffers_addr);
static u32 width = 0; u32 addr = GetAddress(buffers[m_gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL);
static u32 height = 0;
GLenum format = GL_RGBA;
if (m_read_buffer) if (Memory.IsGoodAddr(addr))
{ {
format = GL_BGRA; width = buffers[m_gcm_current_buffer].width;
CellGcmDisplayInfo* buffers = vm::get_ptr<CellGcmDisplayInfo>(m_gcm_buffers_addr); height = buffers[m_gcm_current_buffer].height;
u32 addr = GetAddress(buffers[m_gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL); src_buffer = vm::get_ptr<u8>(addr);
if (Memory.IsGoodAddr(addr))
{
width = buffers[m_gcm_current_buffer].width;
height = buffers[m_gcm_current_buffer].height;
src_buffer = vm::get_ptr<u8>(addr);
}
else
{
src_buffer = nullptr;
}
}
else if (m_fbo.IsCreated())
{
format = GL_RGBA;
static std::vector<u8> 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 else
src_buffer = nullptr;
if (src_buffer)
{ {
glDisable(GL_STENCIL_TEST); src_buffer = nullptr;
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();
} }
} }
break; else if (m_fbo.IsCreated())
{
format = GL_RGBA;
static std::vector<u8> 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 // Draw Objects
for (uint i = 0; i<m_post_draw_objs.size(); ++i) for (uint i = 0; i < m_post_draw_objs.size(); ++i)
{ {
m_post_draw_objs[i].Draw(); m_post_draw_objs[i].Draw();
} }
@ -2198,20 +2132,23 @@ u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height,
{ {
u32 offset = 0; u32 offset = 0;
u32 shift_count = 0; u32 shift_count = 0;
while(log2_width | log2_height | log2_depth){ while (log2_width | log2_height | log2_depth){
if(log2_width){ if (log2_width)
{
offset |= (x & 0x01) << shift_count; offset |= (x & 0x01) << shift_count;
x >>= 1; x >>= 1;
++shift_count; ++shift_count;
--log2_width; --log2_width;
} }
if(log2_height){ if (log2_height)
{
offset |= (y & 0x01) << shift_count; offset |= (y & 0x01) << shift_count;
y >>= 1; y >>= 1;
++shift_count; ++shift_count;
--log2_height; --log2_height;
} }
if(log2_depth){ if (log2_depth)
{
offset |= (z & 0x01) << shift_count; offset |= (z & 0x01) << shift_count;
z >>= 1; z >>= 1;
++shift_count; ++shift_count;

View File

@ -190,7 +190,11 @@ protected:
virtual void OnInitThread(); virtual void OnInitThread();
virtual void OnExitThread(); virtual void OnExitThread();
virtual void OnReset(); virtual void OnReset();
virtual void ExecCMD(u32 cmd);
virtual void ExecCMD(); 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(); virtual void Flip();
}; };

View File

@ -15,34 +15,42 @@
u32 methodRegisters[0xffff]; u32 methodRegisters[0xffff];
void RSXThread::nativeRescale(float width, float height) void RSXThread::NativeRescale(float width, float height)
{ {
switch (Ini.GSResolution.GetValue()) switch (Ini.GSResolution.GetValue())
{ {
case 1: // 1920x1080 window size case 1: // 1920x1080 window size
{
m_width_scale = 1920 / width * 2.0f; m_width_scale = 1920 / width * 2.0f;
m_height_scale = 1080 / height * 2.0f; m_height_scale = 1080 / height * 2.0f;
m_width = 1920; m_width = 1920;
m_height = 1080; m_height = 1080;
break; }
break;
case 2: // 1280x720 window size case 2: // 1280x720 window size
{
m_width_scale = 1280 / width * 2.0f; m_width_scale = 1280 / width * 2.0f;
m_height_scale = 720 / height * 2.0f; m_height_scale = 720 / height * 2.0f;
m_width = 1280; m_width = 1280;
m_height = 720; m_height = 720;
break; }
break;
case 4: // 720x480 window size case 4: // 720x480 window size
{
m_width_scale = 720 / width * 2.0f; m_width_scale = 720 / width * 2.0f;
m_height_scale = 480 / height * 2.0f; m_height_scale = 480 / height * 2.0f;
m_width = 720; m_width = 720;
m_height = 480; m_height = 480;
break; }
break;
case 5: // 720x576 window size case 5: // 720x576 window size
{
m_width_scale = 720 / width * 2.0f; m_width_scale = 720 / width * 2.0f;
m_height_scale = 576 / height * 2.0f; m_height_scale = 576 / height * 2.0f;
m_width = 720; m_width = 720;
m_height = 576; m_height = 576;
break; }
break;
} }
} }
@ -106,13 +114,13 @@ void RSXVertexData::Reset()
void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex=0) void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex=0)
{ {
if(!addr) return; if (!addr) return;
const u32 tsize = GetTypeSize(); const u32 tsize = GetTypeSize();
data.resize((start + count) * tsize * size); data.resize((start + count) * tsize * size);
for(u32 i=start; i<start + count; ++i) for (u32 i = start; i < start + count; ++i)
{ {
auto src = vm::get_ptr<const u8>(addr + baseOffset + stride * (i + baseIndex)); auto src = vm::get_ptr<const u8>(addr + baseOffset + stride * (i + baseIndex));
u8* dst = &data[i * tsize * size]; 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; const u16* c_src = (const u16*)src;
u16* c_dst = (u16*)dst; u16* c_dst = (u16*)dst;
for(u32 j=0; j<size; ++j) *c_dst++ = re16(*c_src++); for (u32 j = 0; j < size; ++j) *c_dst++ = re16(*c_src++);
} }
break; break;
@ -137,7 +145,7 @@ void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex=0)
{ {
const u32* c_src = (const u32*)src; const u32* c_src = (const u32*)src;
u32* c_dst = (u32*)dst; u32* c_dst = (u32*)dst;
for(u32 j=0; j<size; ++j) *c_dst++ = re32(*c_src++); for (u32 j = 0; j < size; ++j) *c_dst++ = re32(*c_src++);
} }
break; break;
} }
@ -167,7 +175,7 @@ u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, cons
auto args = vm::ptr<u32>::make(args_addr); auto args = vm::ptr<u32>::make(args_addr);
std::string debug = GetMethodName(cmd); std::string debug = GetMethodName(cmd);
debug += "("; debug += "(";
for(u32 i=0; i<count; ++i) debug += (i ? ", " : "") + fmt::Format("0x%x", ARGS(i)); for (u32 i = 0; i < count; ++i) debug += (i ? ", " : "") + fmt::Format("0x%x", ARGS(i));
debug += ")"; debug += ")";
LOG_NOTICE(RSX, "OutOfArgsCount(x=%u, count=%u): %s", x, count, debug.c_str()); LOG_NOTICE(RSX, "OutOfArgsCount(x=%u, count=%u): %s", x, count, debug.c_str());
@ -247,7 +255,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV406E_SEMAPHORE_RELEASE: case NV406E_SEMAPHORE_RELEASE:
case NV4097_TEXTURE_READ_SEMAPHORE_RELEASE: case NV4097_TEXTURE_READ_SEMAPHORE_RELEASE:
{ {
if(m_set_semaphore_offset) if (m_set_semaphore_offset)
{ {
m_set_semaphore_offset = false; m_set_semaphore_offset = false;
vm::write32(Memory.RSXCMDMem.GetStartAddr() + m_semaphore_offset, ARGS(0)); vm::write32(Memory.RSXCMDMem.GetStartAddr() + m_semaphore_offset, ARGS(0));
@ -257,7 +265,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE: case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE:
{ {
if(m_set_semaphore_offset) if (m_set_semaphore_offset)
{ {
m_set_semaphore_offset = false; m_set_semaphore_offset = false;
u32 value = ARGS(0); u32 value = ARGS(0);
@ -303,7 +311,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
return; return;
} }
std::this_thread::sleep_for(std::chrono::milliseconds((s64)(1000.0 / limit - m_timer_sync.GetElapsedTimeInMilliSec()))); std::this_thread::sleep_for (std::chrono::milliseconds((s64)(1000.0 / limit - m_timer_sync.GetElapsedTimeInMilliSec())));
m_timer_sync.Start(); m_timer_sync.Start();
}; };
@ -532,13 +540,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
// Color Mask // Color Mask
case NV4097_SET_COLOR_MASK: case NV4097_SET_COLOR_MASK:
{ {
const u32 a0 = ARGS(0); const u32 mask = ARGS(0);
ColorMask(mask & 0x1000000, mask & 0x1000000, mask & 0x1000000, mask & 0x0000001);
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;
} }
break; break;
@ -857,8 +860,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
{ {
u32 a0 = ARGS(0); u32 a0 = ARGS(0);
if(a0 & 0x01) m_clear_surface_z = m_clear_z; if (a0 & 0x01) m_clear_surface_z = m_clear_z;
if(a0 & 0x02) m_clear_surface_s = m_clear_s; if (a0 & 0x02) m_clear_surface_s = m_clear_s;
m_clear_surface_mask |= a0 & 0x3; m_clear_surface_mask |= a0 & 0x3;
} }
@ -866,35 +869,26 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_CLEAR_SURFACE: case NV4097_CLEAR_SURFACE:
{ {
const u32 a0 = ARGS(0); const u32 mask = ARGS(0);
if(a0 & 0x01) m_clear_surface_z = m_clear_z; ClearSurface(mask);
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);
} }
break; break;
case NV4097_SET_ZSTENCIL_CLEAR_VALUE: case NV4097_SET_ZSTENCIL_CLEAR_VALUE:
{ {
const u32 a0 = ARGS(0); const u32 value = ARGS(0);
m_clear_s = a0 & 0xff;
m_clear_z = a0 >> 8; ClearStencil(value & 0xff);
ClearDepth(value >> 8);
} }
break; break;
case NV4097_SET_COLOR_CLEAR_VALUE: case NV4097_SET_COLOR_CLEAR_VALUE:
{ {
const u32 color = ARGS(0); const u32 color = ARGS(0);
m_clear_color_a = (color >> 24) & 0xff;
m_clear_color_r = (color >> 16) & 0xff; ClearColor((color >> 24) & 0xff, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
m_clear_color_g = (color >> 8) & 0xff;
m_clear_color_b = color & 0xff;
} }
break; break;
@ -928,7 +922,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_DRAW_ARRAYS: case NV4097_DRAW_ARRAYS:
{ {
for(u32 c=0; c<count; ++c) for (u32 c=0; c<count; ++c)
{ {
u32 ac = ARGS(c); u32 ac = ARGS(c);
const u32 first = ac & 0xffffff; const u32 first = ac & 0xffffff;
@ -957,14 +951,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_DRAW_INDEX_ARRAY: case NV4097_DRAW_INDEX_ARRAY:
{ {
for(u32 c=0; c<count; ++c) for (u32 c=0; c<count; ++c)
{ {
const u32 first = ARGS(c) & 0xffffff; const u32 first = ARGS(c) & 0xffffff;
const u32 _count = (ARGS(c) >> 24) + 1; const u32 _count = (ARGS(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; u32 index;
switch(m_indexed_array.m_type) 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; break;
} }
if(index < m_indexed_array.index_min) m_indexed_array.index_min = 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; if (index > m_indexed_array.index_max) m_indexed_array.index_max = index;
} }
m_indexed_array.m_count += _count; 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); //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"); LOG_ERROR(RSX, "NV4097_SET_TRANSFORM_PROGRAM: m_cur_vertex_prog is null");
break; break;
@ -1148,7 +1142,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
// TODO: // TODO:
// (cmd)[1] = CELL_GCM_ENDIAN_SWAP((count) | ((registerCount) << 16)); \ // (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"); LOG_ERROR(RSX, "NV4097_SET_TRANSFORM_TIMEOUT: m_cur_vertex_prog is null");
break; 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: 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); LOG_ERROR(RSX, "NV4097_SET_TRANSFORM_CONSTANT_LOAD: bad count %d", count);
break; break;
} }
for(u32 id = ARGS(0), i = 1; i<count; ++id) for (u32 id = ARGS(0), i = 1; i<count; ++id)
{ {
const u32 x = ARGS(i); i++; const u32 x = ARGS(i); i++;
const u32 y = ARGS(i); i++; const u32 y = ARGS(i); i++;
@ -1272,12 +1266,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
m_set_stencil_func = true; m_set_stencil_func = true;
m_stencil_func = ARGS(0); m_stencil_func = ARGS(0);
if(count >= 2) if (count >= 2)
{ {
m_set_stencil_func_ref = true; m_set_stencil_func_ref = true;
m_stencil_func_ref = ARGS(1); m_stencil_func_ref = ARGS(1);
if(count >= 3) if (count >= 3)
{ {
m_set_stencil_func_mask = true; m_set_stencil_func_mask = true;
m_stencil_func_mask = ARGS(2); 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_set_stencil_fail = true;
m_stencil_fail = ARGS(0); m_stencil_fail = ARGS(0);
if(count >= 2) if (count >= 2)
{ {
m_set_stencil_zfail = true; m_set_stencil_zfail = true;
m_stencil_zfail = ARGS(1); m_stencil_zfail = ARGS(1);
if(count >= 3) if (count >= 3)
{ {
m_set_stencil_zpass = true; m_set_stencil_zpass = true;
m_stencil_zpass = ARGS(2); 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_set_back_stencil_func = true;
m_back_stencil_func = ARGS(0); m_back_stencil_func = ARGS(0);
if(count >= 2) if (count >= 2)
{ {
m_set_back_stencil_func_ref = true; m_set_back_stencil_func_ref = true;
m_back_stencil_func_ref = ARGS(1); m_back_stencil_func_ref = ARGS(1);
if(count >= 3) if (count >= 3)
{ {
m_set_back_stencil_func_mask = true; m_set_back_stencil_func_mask = true;
m_back_stencil_func_mask = ARGS(2); 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_set_stencil_fail = true;
m_stencil_fail = ARGS(0); m_stencil_fail = ARGS(0);
if(count >= 2) if (count >= 2)
{ {
m_set_back_stencil_zfail = true; m_set_back_stencil_zfail = true;
m_back_stencil_zfail = ARGS(1); m_back_stencil_zfail = ARGS(1);
if(count >= 3) if (count >= 3)
{ {
m_set_back_stencil_zpass = true; m_set_back_stencil_zpass = true;
m_back_stencil_zpass = ARGS(2); 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_x = ARGS(0) & 0xffff;
m_scissor_w = ARGS(0) >> 16; m_scissor_w = ARGS(0) >> 16;
if(count == 2) if (count == 2)
{ {
m_set_scissor_vertical = true; m_set_scissor_vertical = true;
m_scissor_y = ARGS(1) & 0xffff; 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_width = buffers[m_gcm_current_buffer].width;
m_height = buffers[m_gcm_current_buffer].height; m_height = buffers[m_gcm_current_buffer].height;
nativeRescale((float)m_width, (float)m_height); NativeRescale((float)m_width, (float)m_height);
} }
break; 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_set_context_dma_color_c = true;
m_context_dma_color_c = ARGS(0); m_context_dma_color_c = ARGS(0);
if(count > 1) if (count > 1)
{ {
m_set_context_dma_color_d = true; m_set_context_dma_color_d = true;
m_context_dma_color_d = ARGS(1); 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_x = a0;
m_surface_clip_w = a0 >> 16; m_surface_clip_w = a0 >> 16;
if(count == 2) if (count == 2)
{ {
const u32 a1 = ARGS(1); const u32 a1 = ARGS(1);
m_set_surface_clip_vertical = true; 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; c.y = (float&)a;
} }
if(count >= 3) if (count >= 3)
{ {
u32 a = ARGS(2); u32 a = ARGS(2);
a = a << 16 | a >> 16; a = a << 16 | a >> 16;
c.z = (float&)a; c.z = (float&)a;
} }
if(count >= 4) if (count >= 4)
{ {
u32 a = ARGS(3); u32 a = ARGS(3);
a = a << 16 | a >> 16; a = a << 16 | a >> 16;
c.w = (float&)a; c.w = (float&)a;
} }
if(count >= 5) if (count >= 5)
{ {
LOG_WARNING(RSX, "NV308A_COLOR: count = %d", count); 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", 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); 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; y<m_color_conv_in_h; ++y) for (u16 y=0; y<m_color_conv_in_h; ++y)
{ {
for(u16 x=0; x<m_color_format_src_pitch/4/*m_color_conv_in_w*/; ++x) for (u16 x=0; x<m_color_format_src_pitch/4/*m_color_conv_in_w*/; ++x)
{ {
const u32 src_offset = (m_color_conv_in_y + y) * m_color_format_src_pitch + (m_color_conv_in_x + x) * 4; const u32 src_offset = (m_color_conv_in_y + y) * m_color_format_src_pitch + (m_color_conv_in_x + x) * 4;
const u32 dst_offset = (m_color_conv_out_y + y) * m_color_format_dst_pitch + (m_color_conv_out_x + x) * 4; const u32 dst_offset = (m_color_conv_out_y + y) * m_color_format_dst_pitch + (m_color_conv_out_x + x) * 4;
@ -2280,18 +2274,18 @@ void RSXThread::End()
ExecCMD(); ExecCMD();
for (auto &vdata : m_vertex_data) for (auto &vdata : m_vertex_data)
{
vdata.data.clear(); vdata.data.clear();
}
m_indexed_array.Reset(); m_indexed_array.Reset();
m_fragment_constants.clear(); m_fragment_constants.clear();
m_transform_constants.clear(); m_transform_constants.clear();
m_cur_shader_prog_num = 0; m_cur_shader_prog_num = 0;
//m_cur_shader_prog = nullptr;
m_clear_surface_mask = 0; m_clear_surface_mask = 0;
m_begin_end = 0; m_begin_end = 0;
//Reset();
OnReset(); OnReset();
} }
@ -2333,14 +2327,14 @@ void RSXThread::Task()
continue; continue;
} }
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for (std::chrono::milliseconds(1)); // hack
} }
is_vblank_stopped = true; is_vblank_stopped = true;
}); });
vblank.detach(); vblank.detach();
while(!TestDestroy()) try while (!TestDestroy()) try
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
@ -2354,62 +2348,61 @@ void RSXThread::Task()
u32 get = m_ctrl->get.read_sync(); u32 get = m_ctrl->get.read_sync();
u32 put = m_ctrl->put.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_flip.post_and_wait();
m_sem_flush.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; continue;
} }
//ConLog.Write("addr = 0x%x", m_ioAddress + get);
const u32 cmd = ReadIO32(get); const u32 cmd = ReadIO32(get);
const u32 count = (cmd >> 18) & 0x7ff; const u32 count = (cmd >> 18) & 0x7ff;
//if(cmd == 0) continue;
if (Ini.RSXLogging.GetValue()) if (Ini.RSXLogging.GetValue())
{
LOG_NOTICE(Log::RSX, "%s (cmd=0x%x)", GetMethodName(cmd & 0xffff).c_str(), cmd); 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; 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); //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<u32>::make(offs)); m_ctrl->get.exchange(be_t<u32>::make(offs));
continue; continue;
} }
if(cmd & CELL_GCM_METHOD_FLAG_CALL)
if (cmd & CELL_GCM_METHOD_FLAG_CALL)
{ {
m_call_stack.push(get + 4); m_call_stack.push(get + 4);
u32 offs = cmd & ~3; u32 offs = cmd & ~3;
//u32 addr = offs;
//LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x", offs, cmd, get); //LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x", offs, cmd, get);
m_ctrl->get.exchange(be_t<u32>::make(offs)); m_ctrl->get.exchange(be_t<u32>::make(offs));
continue; 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(); u32 get = m_call_stack.top();
m_call_stack.pop(); m_call_stack.pop();
//LOG_WARNING(RSX, "rsx return(0x%x)", get); //LOG_WARNING(RSX, "rsx return(0x%x)", get);
m_ctrl->get.exchange(be_t<u32>::make(get)); m_ctrl->get.exchange(be_t<u32>::make(get));
continue; 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; inc = 0;
} }
if(cmd == 0) //nop if (cmd == 0) //nop
{ {
m_ctrl->get.atomic_op([](be_t<u32>& value) m_ctrl->get.atomic_op([](be_t<u32>& value)
{ {
@ -2420,7 +2413,7 @@ void RSXThread::Task()
auto args = vm::ptr<u32>::make((u32)Memory.RSXIOMem.RealAddr(get + 4)); auto args = vm::ptr<u32>::make((u32)Memory.RSXIOMem.RealAddr(get + 4));
for(u32 i=0; i<count; i++) for (u32 i = 0; i < count; i++)
{ {
methodRegisters[(cmd & 0xffff) + (i * 4 * inc)] = ARGS(i); methodRegisters[(cmd & 0xffff) + (i * 4 * inc)] = ARGS(i);
} }
@ -2431,13 +2424,14 @@ void RSXThread::Task()
{ {
value += (count + 1) * 4; value += (count + 1) * 4;
}); });
//memset(Memory.GetMemFromAddr(p.m_ioAddress + get), 0, (count + 1) * 4);
} }
catch (const std::string& e) catch (const std::string& e)
{ {
LOG_ERROR(RSX, "Exception: %s", e.c_str()); LOG_ERROR(RSX, "Exception: %s", e.c_str());
Emu.Pause(); Emu.Pause();
} }
catch (const char* e) catch (const char* e)
{ {
LOG_ERROR(RSX, "Exception: %s", e); LOG_ERROR(RSX, "Exception: %s", e);
@ -2446,7 +2440,7 @@ void RSXThread::Task()
while (!is_vblank_stopped) while (!is_vblank_stopped)
{ {
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for (std::chrono::milliseconds(1)); // hack
} }
LOG_NOTICE(RSX, "RSX thread ended"); LOG_NOTICE(RSX, "RSX thread ended");

View File

@ -519,12 +519,15 @@ protected:
m_line_stipple_factor = 1; m_line_stipple_factor = 1;
m_vertex_data_base_offset = 0; m_vertex_data_base_offset = 0;
m_vertex_data_base_index = 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; m_polygon_stipple_pattern[i] = 0xFFFFFFFF;
} }
// Construct Textures // Construct Textures
for(int i=0; i<16; i++) for (int i = 0; i < 16; i++)
{ {
m_textures[i] = RSXTexture(i); m_textures[i] = RSXTexture(i);
} }
@ -611,7 +614,7 @@ protected:
m_clear_surface_mask = 0; m_clear_surface_mask = 0;
m_begin_end = 0; m_begin_end = 0;
for(uint i=0; i<m_textures_count; ++i) for (uint i = 0; i < m_textures_count; ++i)
{ {
m_textures[i].Init(); m_textures[i].Init();
} }
@ -622,19 +625,23 @@ protected:
u32 OutOfArgsCount(const uint x, const u32 cmd, const u32 count, const u32 args_addr); 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 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 OnInit() = 0;
virtual void OnInitThread() = 0; virtual void OnInitThread() = 0;
virtual void OnExitThread() = 0; virtual void OnExitThread() = 0;
virtual void OnReset() = 0; virtual void OnReset() = 0;
virtual void ExecCMD() = 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; virtual void Flip() = 0;
void LoadVertexData(u32 first, u32 count) void LoadVertexData(u32 first, u32 count)
{ {
for(u32 i=0; i<m_vertex_count; ++i) for (u32 i = 0; i < m_vertex_count; ++i)
{ {
if(!m_vertex_data[i].IsEnabled()) continue; if(!m_vertex_data[i].IsEnabled()) continue;