From dbb4bdf59f4958d578e4176d1a1e665dac4d2113 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Fri, 30 Sep 2016 20:04:24 +0200 Subject: [PATCH] gsdx mipmap:ogl: add GL_TEXTURE mipmap support * Allocate more memory for extra layers * Allow to upload data in any layers --- plugins/GSdx/GSDeviceOGL.cpp | 6 ++++-- plugins/GSdx/GSDeviceOGL.h | 1 + plugins/GSdx/GSTextureOGL.cpp | 20 +++++++++++++++----- plugins/GSdx/GSTextureOGL.h | 4 +++- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 42f9d58553..3913747b4d 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -74,6 +74,8 @@ GSDeviceOGL::GSDeviceOGL() memset(&m_profiler, 0 , sizeof(m_profiler)); GLState::Clear(); + m_mipmap = theApp.GetConfigI("mipmap"); + // Reset the debug file #ifdef ENABLE_OGL_DEBUG m_debug_gl_file = fopen("GSdx_opengl_debug.txt","w"); @@ -227,7 +229,7 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int fmt // A wrapper to call GSTextureOGL, with the different kind of parameter GSTextureOGL* t = NULL; - t = new GSTextureOGL(type, w, h, fmt, m_fbo_read); + t = new GSTextureOGL(type, w, h, fmt, m_fbo_read, m_mipmap > 1); if (t == NULL) { throw GSDXErrorOOM(); } @@ -593,7 +595,7 @@ bool GSDeviceOGL::Reset(int w, int h) // Opengl allocate the backbuffer with the window. The render is done in the backbuffer when // there isn't any FBO. Only a dummy texture is created to easily detect when the rendering is done // in the backbuffer - m_backbuffer = new GSTextureOGL(GSTextureOGL::Backbuffer, w, h, 0, m_fbo_read); + m_backbuffer = new GSTextureOGL(GSTextureOGL::Backbuffer, w, h, 0, m_fbo_read, false); return true; } diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index 09cb4645bf..60d5560916 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -401,6 +401,7 @@ public: private: uint32 m_msaa; // Level of Msaa int m_force_texture_clear; + int m_mipmap; static bool m_debug_gl_call; static FILE* m_debug_gl_file; diff --git a/plugins/GSdx/GSTextureOGL.cpp b/plugins/GSdx/GSTextureOGL.cpp index 1b756446c3..691d661e82 100644 --- a/plugins/GSdx/GSTextureOGL.cpp +++ b/plugins/GSdx/GSTextureOGL.cpp @@ -152,8 +152,8 @@ namespace PboPool { } } -GSTextureOGL::GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read) - : m_pbo_size(0), m_clean(false), m_local_buffer(NULL), m_r_x(0), m_r_y(0), m_r_w(0), m_r_h(0) +GSTextureOGL::GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read, bool mipmap) + : m_pbo_size(0), m_clean(false), m_local_buffer(NULL), m_r_x(0), m_r_y(0), m_r_w(0), m_r_h(0), m_layer(0) { // OpenGL didn't like dimensions of size 0 m_size.x = max(1,w); @@ -249,6 +249,9 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read) throw GSDXErrorOOM(); } + // Only 32 bits input texture will be supported for mipmap + m_max_layer = mipmap && (m_type == GSTexture::Texture) && m_format == GL_RGBA8 ? (int)log2(max(w,h)) : 1; + // Generate & Allocate the buffer switch (m_type) { case GSTexture::Offscreen: @@ -258,7 +261,7 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read) case GSTexture::RenderTarget: case GSTexture::DepthStencil: glCreateTextures(GL_TEXTURE_2D, 1, &m_texture_id); - glTextureStorage2D(m_texture_id, 1+GL_TEX_LEVEL_0, m_format, m_size.x, m_size.y); + glTextureStorage2D(m_texture_id, m_max_layer + GL_TEX_LEVEL_0, m_format, m_size.x, m_size.y); if (m_format == GL_R8) { // Emulate DX behavior, beside it avoid special code in shader to differentiate // palette texture from a GL_RGBA target or a GL_R texture. @@ -306,6 +309,9 @@ bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch, int { ASSERT(m_type != GSTexture::DepthStencil && m_type != GSTexture::Offscreen); + if (layer >= m_max_layer) + return true; + // Default upload path for the texture is the Map/Unmap // This path is mostly used for palette. But also for texture that could // overflow the pbo buffer @@ -356,7 +362,7 @@ bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch, int PboPool::Unmap(); - glTextureSubImage2D(m_texture_id, GL_TEX_LEVEL_0, r.x, r.y, r.width(), r.height(), m_int_format, m_int_type, (const void*)PboPool::Offset()); + glTextureSubImage2D(m_texture_id, layer, r.x, r.y, r.width(), r.height(), m_int_format, m_int_type, (const void*)PboPool::Offset()); // FIXME OGL4: investigate, only 1 unpack buffer always bound PboPool::UnbindPbo(); @@ -369,6 +375,9 @@ bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch, int bool GSTextureOGL::Map(GSMap& m, const GSVector4i* _r, int layer) { + if (layer >= m_max_layer) + return false; + GSVector4i r = _r ? *_r : GSVector4i(0, 0, m_size.x, m_size.y); // Will need some investigation ASSERT(r.width() != 0); @@ -422,6 +431,7 @@ bool GSTextureOGL::Map(GSMap& m, const GSVector4i* _r, int layer) m_r_y = r.y; m_r_w = r.width(); m_r_h = r.height(); + m_layer = layer; return true; } @@ -435,7 +445,7 @@ void GSTextureOGL::Unmap() PboPool::Unmap(); - glTextureSubImage2D(m_texture_id, GL_TEX_LEVEL_0, m_r_x, m_r_y, m_r_w, m_r_h, m_int_format, m_int_type, (const void*)PboPool::Offset()); + glTextureSubImage2D(m_texture_id, m_layer, m_r_x, m_r_y, m_r_w, m_r_h, m_int_format, m_int_type, (const void*)PboPool::Offset()); // FIXME OGL4: investigate, only 1 unpack buffer always bound PboPool::UnbindPbo(); diff --git a/plugins/GSdx/GSTextureOGL.h b/plugins/GSdx/GSTextureOGL.h index c0eec6efe8..1dd4f37289 100644 --- a/plugins/GSdx/GSTextureOGL.h +++ b/plugins/GSdx/GSTextureOGL.h @@ -52,6 +52,8 @@ class GSTextureOGL final : public GSTexture int m_r_y; int m_r_w; int m_r_h; + int m_layer; + int m_max_layer; // internal opengl format/type/alignment GLenum m_int_format; @@ -62,7 +64,7 @@ class GSTextureOGL final : public GSTexture uint32 m_mem_usage; public: - explicit GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read); + explicit GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read, bool mipmap); virtual ~GSTextureOGL(); bool Update(const GSVector4i& r, const void* data, int pitch, int layer = 0) final;