diff --git a/plugins/GSdx/GPURendererSW.cpp b/plugins/GSdx/GPURendererSW.cpp index 030741dcb2..c71f72fdcb 100644 --- a/plugins/GSdx/GPURendererSW.cpp +++ b/plugins/GSdx/GPURendererSW.cpp @@ -32,7 +32,6 @@ GPURendererSW::GPURendererSW(GSDevice* dev) GPURendererSW::~GPURendererSW() { - m_rl.Terminate(); } void GPURendererSW::ResetDevice() diff --git a/plugins/GSdx/GS.cpp b/plugins/GSdx/GS.cpp index cecc1019e7..bf7ce343c9 100644 --- a/plugins/GSdx/GS.cpp +++ b/plugins/GSdx/GS.cpp @@ -602,4 +602,4 @@ EXPORT_C GSBenchmark(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow fclose(file); } -#endif \ No newline at end of file +#endif diff --git a/plugins/GSdx/GSDevice.cpp b/plugins/GSdx/GSDevice.cpp index 234c244c28..12d757278e 100644 --- a/plugins/GSdx/GSDevice.cpp +++ b/plugins/GSdx/GSDevice.cpp @@ -167,8 +167,15 @@ void GSDevice::Merge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, const GSVec // KH:COM crashes at startup when booting *through the bios* due to m_merge being NULL. // (texture appears to be non-null, and is being re-created at a size around like 1700x340, // dunno if that's relevant) -- air - if( m_merge ) + + if(m_merge) + { DoMerge(st, sr, dr, m_merge, slbg, mmod, c); + } + else + { + printf("GSdx: m_merge is NULL!\n"); + } m_current = m_merge; } diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index c503b7c084..8c8e929ed2 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -30,6 +30,8 @@ GSDeviceOGL::GSDeviceOGL() , m_vbo(0) , m_fbo(0) , m_topology(-1) + , m_rt((GLuint)-1) + , m_ds((GLuint)-1) { m_vertices.stride = 0; m_vertices.start = 0; @@ -110,10 +112,26 @@ bool GSDeviceOGL::Create(GSWnd* wnd, bool vsync) return false; } - // const char* exts = (const char*)glGetString(GL_EXTENSIONS); + #ifdef _WINDOWS - glGenBuffers(1, &m_vbo); - glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + if(WGLEW_EXT_swap_control) + { + wglSwapIntervalEXT(vsync ? 1 : 0); + } + + #endif + + const char* vendor = (const char*)glGetString(GL_VENDOR); + const char* renderer = (const char*)glGetString(GL_RENDERER); + const char* version = (const char*)glGetString(GL_VERSION); + const char* exts = (const char*)glGetString(GL_EXTENSIONS); + + printf("%s, %s, OpenGL %s\n", vendor, renderer, version); + + const char* str = strstr(exts, "ARB_texture_non_power_of_two"); + + glGenBuffers(1, &m_vbo); CheckError(); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); CheckError(); // TODO: setup layout? GSVector4i r = wnd->GetClientRect(); @@ -128,33 +146,40 @@ bool GSDeviceOGL::Reset(int w, int h, bool fs) if(!__super::Reset(w, h, fs)) return false; - m_backbuffer = new GSTextureOGL(0, GSTexture::RenderTarget, w, h); + glCullFace(GL_FRONT_AND_BACK); CheckError(); + glDisable(GL_LIGHTING); CheckError(); + glDisable(GL_ALPHA_TEST); CheckError(); + glEnable(GL_SCISSOR_TEST); CheckError(); - glCullFace(GL_FRONT_AND_BACK); - glDisable(GL_LIGHTING); - glDisable(GL_ALPHA_TEST); - glEnable(GL_SCISSOR_TEST); + glMatrixMode(GL_PROJECTION); CheckError(); + glLoadIdentity(); CheckError(); + glMatrixMode(GL_MODELVIEW); CheckError(); + glLoadIdentity(); CheckError(); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); CheckError(); // glViewport(0, 0, w, h); if(m_fbo) {glDeleteFramebuffersEXT(1, &m_fbo); m_fbo = 0;} - glGenFramebuffers(1, &m_fbo); + glGenFramebuffers(1, &m_fbo); CheckError(); if(m_fbo == 0) return false; - glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); CheckError(); return true; } +void GSDeviceOGL::Present(const GSVector4i& r, int shader) +{ + glBindFramebuffer(GL_FRAMEBUFFER, 0); CheckError(); + + // TODO: m_current => backbuffer + + Flip(); +} + void GSDeviceOGL::Flip() { #ifdef _WINDOWS @@ -170,7 +195,7 @@ void GSDeviceOGL::BeginScene() void GSDeviceOGL::DrawPrimitive() { - glDrawArrays(m_topology, m_vertices.count, m_vertices.start); + glDrawArrays(m_topology, m_vertices.count, m_vertices.start); CheckError(); } void GSDeviceOGL::EndScene() @@ -181,10 +206,21 @@ void GSDeviceOGL::EndScene() void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c) { + GLuint texture = *(GSTextureOGL*)t; + + if(texture == 0) + { + // TODO: backbuffer + } + else + { + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, texture); CheckError(); + } + // TODO: disable scissor, color mask - glClearColor(c.r, c.g, c.b, c.a); - glClear(GL_COLOR_BUFFER_BIT); + glClearColor(c.r, c.g, c.b, c.a); CheckError(); + glClear(GL_COLOR_BUFFER_BIT); CheckError(); } void GSDeviceOGL::ClearRenderTarget(GSTexture* t, uint32 c) @@ -194,18 +230,22 @@ void GSDeviceOGL::ClearRenderTarget(GSTexture* t, uint32 c) void GSDeviceOGL::ClearDepth(GSTexture* t, float c) { + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, *(GSTextureOGL*)t); CheckError(); + // TODO: disable scissor, depth mask - glClearDepth(c); - glClear(GL_DEPTH_BUFFER_BIT); + glClearDepth(c); CheckError(); + glClear(GL_DEPTH_BUFFER_BIT); CheckError(); } void GSDeviceOGL::ClearStencil(GSTexture* t, uint8 c) { + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX, *(GSTextureOGL*)t); CheckError(); + // TODO: disable scissor, depth (?) mask - glClearStencil((GLint)c); - glClear(GL_STENCIL_BUFFER_BIT); + glClearStencil((GLint)c); CheckError(); + glClear(GL_STENCIL_BUFFER_BIT); CheckError(); } GSTexture* GSDeviceOGL::Create(int type, int w, int h, int format) @@ -215,20 +255,20 @@ GSTexture* GSDeviceOGL::Create(int type, int w, int h, int format) switch(type) { case GSTexture::RenderTarget: - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glGenTextures(1, &texture); CheckError(); + glBindTexture(GL_TEXTURE_2D, texture); CheckError(); + glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); CheckError(); break; case GSTexture::DepthStencil: - glGenRenderbuffersEXT(1, &texture); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, texture); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH32F_STENCIL8, w, h); + glGenRenderbuffers(1, &texture); CheckError(); + glBindRenderbuffer(GL_RENDERBUFFER, texture); CheckError(); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH32F_STENCIL8, w, h); CheckError(); // TODO: depth textures? break; case GSTexture::Texture: - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glGenTextures(1, &texture); CheckError(); + glBindTexture(GL_TEXTURE_2D, texture); CheckError(); + glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); CheckError(); break; case GSTexture::Offscreen: // TODO: ??? @@ -298,34 +338,41 @@ void GSDeviceOGL::IASetVertexBuffer(const void* vertices, size_t stride, size_t { ASSERT(m_vertices.count == 0); - glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); CheckError(); + + bool growbuffer = false; + bool discard = false; // in opengl 3.x this should be a flag to glMapBuffer, as I read somewhere if(count * stride > m_vertices.limit * m_vertices.stride) { m_vertices.start = 0; m_vertices.count = 0; - m_vertices.limit = 0; - } - - if(m_vertices.limit == 0) - { m_vertices.limit = max(count * 3 / 2, 10000); - glBufferData(GL_ARRAY_BUFFER, m_vertices.limit * stride, NULL, GL_DYNAMIC_DRAW); // GL_STREAM_DRAW? + growbuffer = true; } if(m_vertices.start + count > m_vertices.limit || stride != m_vertices.stride) { - m_vertices.start = 0; // TODO: how to discard and not overwrite previous data? + m_vertices.start = 0; + + discard = true; } + if(growbuffer || discard) + { + glBufferData(GL_ARRAY_BUFFER, m_vertices.limit * stride, NULL, GL_DYNAMIC_DRAW); CheckError(); // GL_STREAM_DRAW? + } + + glBufferSubData(GL_ARRAY_BUFFER, m_vertices.start * stride, count * stride, vertices); CheckError(); +/* if(GLvoid* v = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY)) { GSVector4i::storent((uint8*)v + m_vertices.start * stride, vertices, count * stride); - glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_ARRAY_BUFFER); CheckError(); } - +*/ m_vertices.count = count; m_vertices.stride = stride; } @@ -340,3 +387,25 @@ void GSDeviceOGL::IASetPrimitiveTopology(int topology) m_topology = topology; } +void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds) +{ + GLuint rti = 0; + GLuint dsi = 0; + + if(rt) rti = *(GSTextureOGL*)rt; + if(ds) dsi = *(GSTextureOGL*)ds; + + // TODO: if(m_rt != rti) + { + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rti); CheckError(); + + // TODO: m_rt = rti; + } + + // TODO: if(m_ds != dsi) + { + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, dsi); CheckError(); + + // TODO: m_ds = dsi; + } +} diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index 32c510b2d1..d95b8916b3 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -42,6 +42,8 @@ class GSDeviceOGL : public GSDevice } m_vertices; int m_topology; + GLuint m_rt; + GLuint m_ds; // @@ -62,6 +64,7 @@ public: bool Create(GSWnd* wnd, bool vsync); bool Reset(int w, int h, bool fs); + void Present(const GSVector4i& r, int shader); void Flip(); void BeginScene(); @@ -85,4 +88,30 @@ public: void IASetVertexBuffer(const void* vertices, size_t stride, size_t count); void IASetInputLayout(); // TODO void IASetPrimitiveTopology(int topology); + + void OMSetRenderTargets(GSTexture* rt, GSTexture* ds); + + static void CheckError() + { + #ifdef _DEBUG + + GLenum error = glGetError(); + + if(error != GL_NO_ERROR) + { + printf("%s\n", gluErrorString(error)); + } + + #endif + } + + static void CheckFrameBuffer() + { + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + if(status != GL_FRAMEBUFFER_COMPLETE) + { + printf("%d\n", status); + } + } }; diff --git a/plugins/GSdx/GSRasterizer.cpp b/plugins/GSdx/GSRasterizer.cpp index 1dcf723e75..abd730281a 100644 --- a/plugins/GSdx/GSRasterizer.cpp +++ b/plugins/GSdx/GSRasterizer.cpp @@ -823,12 +823,9 @@ GSRasterizerMT::GSRasterizerMT(IDrawScanline* ds, int id, int threads, long* syn } } -GSRasterizerMT::~GSRasterizerMT() {} - -void GSRasterizerMT::Terminate() +GSRasterizerMT::~GSRasterizerMT() { m_exit = true; - CloseThread(); } void GSRasterizerMT::Draw(const GSRasterizerData* data) @@ -879,15 +876,9 @@ GSRasterizerList::GSRasterizerList() GSRasterizerList::~GSRasterizerList() { - _aligned_free(m_sync); -} + FreeRasterizers(); -void GSRasterizerList::Terminate() -{ - for(list::iterator i = begin(); i != end(); i++) - { - (*i)->Terminate(); - } + _aligned_free(m_sync); } void GSRasterizerList::FreeRasterizers() diff --git a/plugins/GSdx/GSRasterizer.h b/plugins/GSdx/GSRasterizer.h index a35148571c..00a2009baf 100644 --- a/plugins/GSdx/GSRasterizer.h +++ b/plugins/GSdx/GSRasterizer.h @@ -43,7 +43,6 @@ public: virtual void Draw(const GSRasterizerData* data) = 0; virtual void GetStats(GSRasterizerStats& stats) = 0; - virtual void Terminate() = 0; virtual void PrintStats() = 0; }; @@ -102,7 +101,6 @@ public: void Draw(const GSRasterizerData* data); void GetStats(GSRasterizerStats& stats); void PrintStats() {m_ds->PrintStats();} - void Terminate() {} }; class GSRasterizerMT : public GSRasterizer, private GSThread @@ -120,7 +118,6 @@ public: // IRasterizer void Draw(const GSRasterizerData* data); - void Terminate(); }; class GSRasterizerList : protected list, public IRasterizer @@ -151,5 +148,4 @@ public: void Draw(const GSRasterizerData* data); void GetStats(GSRasterizerStats& stats); void PrintStats(); - void Terminate(); }; diff --git a/plugins/GSdx/GSRendererSW.cpp b/plugins/GSdx/GSRendererSW.cpp index 40a7c93b7d..d9e0d732b6 100644 --- a/plugins/GSdx/GSRendererSW.cpp +++ b/plugins/GSdx/GSRendererSW.cpp @@ -38,8 +38,6 @@ GSRendererSW::GSRendererSW(uint8* base, bool mt, void (*irq)(), GSDevice* dev) GSRendererSW::~GSRendererSW() { - m_rl.Terminate(); - delete m_tc; } diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index 3c84591fc9..59e7a8ac7d 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -219,4 +219,4 @@ void GSSettingsDlg::UpdateControls() EnableWindow(GetDlgItem(m_hWnd, IDC_SWTHREADS_EDIT), sw); EnableWindow(GetDlgItem(m_hWnd, IDC_SWTHREADS), sw); } -} \ No newline at end of file +} diff --git a/plugins/GSdx/GSTextureOGL.cpp b/plugins/GSdx/GSTextureOGL.cpp index 3e8f1f97eb..ca59491c72 100644 --- a/plugins/GSdx/GSTextureOGL.cpp +++ b/plugins/GSdx/GSTextureOGL.cpp @@ -21,6 +21,7 @@ #include "stdafx.h" #include "GSTextureOGL.h" +#include "GSDeviceOGL.h" GSTextureOGL::GSTextureOGL(GLuint texture, int type, int width, int height, int format) : m_texture(texture) @@ -29,19 +30,27 @@ GSTextureOGL::GSTextureOGL(GLuint texture, int type, int width, int height, int , m_height(height) , m_format(format) { + // TODO: offscreen type should be just a memory array, also returned in Map + + glGenBuffers(1, &m_pbo); GSDeviceOGL::CheckError(); } GSTextureOGL::~GSTextureOGL() { + if(m_pbo) + { + glDeleteBuffers(1, &m_pbo); GSDeviceOGL::CheckError(); + } + if(m_texture) { switch(m_type) { case DepthStencil: - glDeleteRenderbuffersEXT(1, &m_texture); + glDeleteRenderbuffers(1, &m_texture); GSDeviceOGL::CheckError(); break; default: - glDeleteTextures(1, &m_texture); + glDeleteTextures(1, &m_texture); GSDeviceOGL::CheckError(); break; } } @@ -69,7 +78,32 @@ int GSTextureOGL::GetFormat() const bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch) { - // TODO: glTexSubImage2D looks like UpdateSubresource but does not take a pitch + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo); GSDeviceOGL::CheckError(); + + int w = r.width(); + int h = r.height(); + int bpp = 32; // TODO: should be in sync with m_format + int dstpitch = w * bpp >> 3; + + glBufferData(GL_PIXEL_UNPACK_BUFFER, h * dstpitch, NULL, GL_STREAM_DRAW); GSDeviceOGL::CheckError(); + + if(uint8* dst = (uint8*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY)) + { + uint8* src = (uint8*)data; + + for(int i = 0; i < h; i++, src += pitch, dst += dstpitch) + { + memcpy(dst, src, dstpitch); + } + + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); GSDeviceOGL::CheckError(); + } + + glBindTexture(GL_TEXTURE_2D, m_texture); GSDeviceOGL::CheckError(); + + glTexSubImage2D(GL_TEXTURE_2D, 0, r.left, r.top, w, h, GL_RGBA, GL_UNSIGNED_BYTE, 0); GSDeviceOGL::CheckError(); + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); GSDeviceOGL::CheckError(); return false; } diff --git a/plugins/GSdx/GSTextureOGL.h b/plugins/GSdx/GSTextureOGL.h index 5e6e2a7926..d69581a697 100644 --- a/plugins/GSdx/GSTextureOGL.h +++ b/plugins/GSdx/GSTextureOGL.h @@ -26,6 +26,7 @@ class GSTextureOGL : public GSTexture { GLuint m_texture; + GLuint m_pbo; int m_type; int m_width; @@ -45,4 +46,6 @@ public: bool Map(GSMap& m, const GSVector4i* r); void Unmap(); bool Save(const string& fn, bool dds = false); + + operator GLuint() {return m_texture;} };