From e5e234b864e75862a2de72ee6c3b8bda47f41c23 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 10 Dec 2015 16:42:56 +0100 Subject: OPENGL: Refactor GL extension handling slightly. --- backends/graphics/opengl/texture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 7b0b22d630..36fe5ab744 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -105,7 +105,7 @@ void Texture::enableLinearFiltering(bool enable) { void Texture::allocate(uint width, uint height) { uint texWidth = width, texHeight = height; - if (!g_extNPOTSupported) { + if (!g_extensions.NPOTSupported) { texWidth = nextHigher2(texWidth); texHeight = nextHigher2(texHeight); } -- cgit v1.2.3 From b3b3d37e3b8231ec345a2d4172279373d53a0c79 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 11 Dec 2015 23:58:11 +0100 Subject: OPENGL: Define GLCALL in opengl-sys.h. debug.h is now always included and all calls should be made through GLCALL. --- backends/graphics/opengl/texture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 36fe5ab744..696e1e6252 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -22,7 +22,7 @@ #include "backends/graphics/opengl/texture.h" #include "backends/graphics/opengl/extensions.h" -#include "backends/graphics/opengl/debug.h" +#include "backends/graphics/opengl/opengl-graphics.h" #include "common/rect.h" #include "common/textconsole.h" -- cgit v1.2.3 From 4a781737c1da77015df4547f64f2f88966816343 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 12 Dec 2015 01:18:46 +0100 Subject: OPENGL: Resolve OpenGL functions on run-time. Formerly we relied on static linkage. However, in the presense of modern OpenGL (ES) implementations it is not easily identifable which library to link against. For example, on Linux amd64 with nVidia drivers and SDL2 setup to create a GLES 1.1 context one would need to link against libGL.so. However, traditionally GLES 1.1 required to link against libGLESv1_CM.so. To prevent a huge mess we simply resolve the OpenGL functions on run-time now and stop linking against a static library (in most cases). GLES support needs to be enabled manually on configure time for now. Tizen changes have NOT been tested. --- backends/graphics/opengl/texture.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 696e1e6252..bc255004e7 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -21,8 +21,6 @@ */ #include "backends/graphics/opengl/texture.h" -#include "backends/graphics/opengl/extensions.h" -#include "backends/graphics/opengl/opengl-graphics.h" #include "common/rect.h" #include "common/textconsole.h" @@ -44,7 +42,7 @@ static GLuint nextHigher2(GLuint v) { GLint Texture::_maxTextureSize = 0; void Texture::queryTextureInformation() { - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_maxTextureSize); + GLCALL(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_maxTextureSize)); debug(5, "OpenGL maximum texture size: %d", _maxTextureSize); } @@ -105,7 +103,7 @@ void Texture::enableLinearFiltering(bool enable) { void Texture::allocate(uint width, uint height) { uint texWidth = width, texHeight = height; - if (!g_extensions.NPOTSupported) { + if (!g_context.NPOTSupported) { texWidth = nextHigher2(texWidth); texHeight = nextHigher2(texHeight); } -- cgit v1.2.3 From e11f4df1118eb0858f4d3bfda697e63174d5e2d1 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 12 Dec 2015 03:22:51 +0100 Subject: OPENGL: Rename GLCALL to GL_CALL. --- backends/graphics/opengl/texture.cpp | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index bc255004e7..b866b15bfd 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -42,7 +42,7 @@ static GLuint nextHigher2(GLuint v) { GLint Texture::_maxTextureSize = 0; void Texture::queryTextureInformation() { - GLCALL(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_maxTextureSize)); + GL_CALL(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_maxTextureSize)); debug(5, "OpenGL maximum texture size: %d", _maxTextureSize); } @@ -58,7 +58,7 @@ Texture::~Texture() { } void Texture::releaseInternalTexture() { - GLCALL(glDeleteTextures(1, &_glTexture)); + GL_CALL(glDeleteTextures(1, &_glTexture)); _glTexture = 0; } @@ -67,20 +67,20 @@ void Texture::recreateInternalTexture() { releaseInternalTexture(); // Get a new texture name. - GLCALL(glGenTextures(1, &_glTexture)); + GL_CALL(glGenTextures(1, &_glTexture)); // Set up all texture parameters. - GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); - GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); // In case there is an actual texture setup we reinitialize it. if (_textureData.getPixels()) { // Allocate storage for OpenGL texture. - GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w, + GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w, _textureData.h, 0, _glFormat, _glType, NULL)); // Mark dirts such that it will be completely refreshed the next time. @@ -95,10 +95,10 @@ void Texture::enableLinearFiltering(bool enable) { _glFilter = GL_NEAREST; } - GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter)); } void Texture::allocate(uint width, uint height) { @@ -115,10 +115,10 @@ void Texture::allocate(uint width, uint height) { _textureData.create(texWidth, texHeight, _format); // Set the texture. - GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); // Allocate storage for OpenGL texture. - GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w, + GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w, _textureData.h, 0, _glFormat, _glType, NULL)); } @@ -174,7 +174,7 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { updateTexture(); // Set the texture. - GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); // Calculate the texture rect that will be drawn. const GLfloat texWidth = (GLfloat)_userPixelData.w / _textureData.w; @@ -185,7 +185,7 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { 0, texHeight, texWidth, texHeight }; - GLCALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords)); + GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords)); // Calculate the screen rect where the texture will be drawn. const GLfloat vertices[4*2] = { @@ -194,10 +194,10 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { x, y + h, x + w, y + h }; - GLCALL(glVertexPointer(2, GL_FLOAT, 0, vertices)); + GL_CALL(glVertexPointer(2, GL_FLOAT, 0, vertices)); // Draw the texture to the screen buffer. - GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); + GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); } void Texture::updateTexture() { @@ -237,7 +237,7 @@ void Texture::updateTexture() { } // Set the texture. - GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); // Update the actual texture. // Although we keep track of the dirty part of the texture buffer we @@ -257,7 +257,7 @@ void Texture::updateTexture() { // // 3) Use glTexSubImage2D per line changed. This is what the old OpenGL // graphics manager did but it is much slower! Thus, we do not use it. - GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, dirtyArea.top, _textureData.w, dirtyArea.height(), + GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, dirtyArea.top, _textureData.w, dirtyArea.height(), _glFormat, _glType, _textureData.getBasePtr(0, dirtyArea.top))); // We should have handled everything, thus not dirty anymore. -- cgit v1.2.3 From 22771446238784eede905b5471c3ae8784523641 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 15 Dec 2015 02:48:42 +0100 Subject: OPENGL: Support RGB555 for OpenGL ES output. This mode should *not* be used by any new engines/code. If someone is going to use it and says it works with the OpenGL output, please make them wear a red uniform and beam them onto a remote planet. --- backends/graphics/opengl/texture.cpp | 60 ++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index b866b15bfd..fadfd99aaa 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -369,4 +369,64 @@ void TextureCLUT8::updateTexture() { Texture::updateTexture(); } +#if !USE_FORCED_GL +TextureRGB555::TextureRGB555() + : Texture(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)), + _rgb555Data() { +} + +TextureRGB555::~TextureRGB555() { + _rgb555Data.free(); +} + +void TextureRGB555::allocate(uint width, uint height) { + Texture::allocate(width, height); + + // We only need to reinitialize our RGB555 surface when the output size + // changed. + if (width == _rgb555Data.w && height == _rgb555Data.h) { + return; + } + + _rgb555Data.create(width, height, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)); +} + +Graphics::PixelFormat TextureRGB555::getFormat() const { + return Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); +} + +void TextureRGB555::updateTexture() { + if (!isDirty()) { + return; + } + + // Convert color space. + Graphics::Surface *outSurf = Texture::getSurface(); + + const Common::Rect dirtyArea = getDirtyArea(); + + uint16 *dst = (uint16 *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top); + const uint dstAdd = outSurf->pitch - 2 * dirtyArea.width(); + + const uint16 *src = (const uint16 *)_rgb555Data.getBasePtr(dirtyArea.left, dirtyArea.top); + const uint srcAdd = _rgb555Data.pitch - 2 * dirtyArea.width(); + + for (int height = dirtyArea.height(); height > 0; --height) { + for (int width = dirtyArea.width(); width > 0; --width) { + const uint16 color = *src++; + + *dst++ = ((color & 0x7C00) << 1) // R + | (((color & 0x03E0) << 1) | ((color & 0x0200) >> 4)) // G + | (color & 0x001F); // B + } + + src = (const uint16 *)((const byte *)src + srcAdd); + dst = (uint16 *)((byte *)dst + dstAdd); + } + + // Do generic handling of updating the texture. + Texture::updateTexture(); +} +#endif // !USE_FORCED_GL + } // End of namespace OpenGL -- cgit v1.2.3 From fe88375ff376cbb0d940c96ac6ec1667be4acab0 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 20 Dec 2015 05:42:54 +0100 Subject: OPENGL: Support GLES2 contexts. --- backends/graphics/opengl/texture.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index fadfd99aaa..c8c38edbbd 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -21,6 +21,7 @@ */ #include "backends/graphics/opengl/texture.h" +#include "backends/graphics/opengl/shader.h" #include "common/rect.h" #include "common/textconsole.h" @@ -185,7 +186,6 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { 0, texHeight, texWidth, texHeight }; - GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords)); // Calculate the screen rect where the texture will be drawn. const GLfloat vertices[4*2] = { @@ -194,7 +194,24 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { x, y + h, x + w, y + h }; - GL_CALL(glVertexPointer(2, GL_FLOAT, 0, vertices)); + +#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 + if (g_context.type != kContextGLES2) { +#endif +#if !USE_FORCED_GLES2 + GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords)); + GL_CALL(glVertexPointer(2, GL_FLOAT, 0, vertices)); +#endif +#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 + } else { +#endif +#if !USE_FORCED_GL && !USE_FORCED_GLES + GL_CALL(glVertexAttribPointer(kTexCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords)); + GL_CALL(glVertexAttribPointer(kPositionAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices)); +#endif +#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 + } +#endif // Draw the texture to the screen buffer. GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); -- cgit v1.2.3 From fee1aa550203c3f46ff19afbe19a7baa4771a5cd Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 20 Dec 2015 09:30:11 +0100 Subject: OPENGL: Add support for shaders with GL contexts. --- backends/graphics/opengl/texture.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index c8c38edbbd..0b01430728 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -196,18 +196,27 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { }; #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - if (g_context.type != kContextGLES2) { + if (g_context.type == kContextGLES2) { #endif -#if !USE_FORCED_GLES2 - GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords)); - GL_CALL(glVertexPointer(2, GL_FLOAT, 0, vertices)); +#if !USE_FORCED_GL && !USE_FORCED_GLES + GL_CALL(glVertexAttribPointer(kTexCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords)); + GL_CALL(glVertexAttribPointer(kPositionAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices)); #endif #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 } else { #endif -#if !USE_FORCED_GL && !USE_FORCED_GLES - GL_CALL(glVertexAttribPointer(kTexCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords)); - GL_CALL(glVertexAttribPointer(kPositionAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices)); +#if !USE_FORCED_GLES2 +#if !USE_FORCED_GLES + if (g_context.shadersSupported) { + GL_CALL(glVertexAttribPointerARB(kTexCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords)); + GL_CALL(glVertexAttribPointerARB(kPositionAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices)); + } else { +#endif + GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords)); + GL_CALL(glVertexPointer(2, GL_FLOAT, 0, vertices)); +#if !USE_FORCED_GLES + } +#endif #endif #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 } -- cgit v1.2.3 From d029f167996f3328ac278829802d9c1a32c620e2 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 20 Dec 2015 09:50:55 +0100 Subject: OPENGL: Handle destruction gracefully when no context is setup. --- backends/graphics/opengl/texture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 0b01430728..e394f760f9 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -54,7 +54,7 @@ Texture::Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graph } Texture::~Texture() { - releaseInternalTexture(); + GL_CALL_SAFE(glDeleteTextures, (1, &_glTexture)); _textureData.free(); } -- cgit v1.2.3 From c7c870bf7f269229d069d47c22b61c237737cdae Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 21 Dec 2015 05:05:37 +0100 Subject: OPENGL: (Partly) move context specific handling to Context. This does not include (most) shader setup, and projection matrices yet. --- backends/graphics/opengl/texture.cpp | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index e394f760f9..08f5e69f03 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -195,32 +195,8 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { x + w, y + h }; -#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - if (g_context.type == kContextGLES2) { -#endif -#if !USE_FORCED_GL && !USE_FORCED_GLES - GL_CALL(glVertexAttribPointer(kTexCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords)); - GL_CALL(glVertexAttribPointer(kPositionAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices)); -#endif -#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - } else { -#endif -#if !USE_FORCED_GLES2 -#if !USE_FORCED_GLES - if (g_context.shadersSupported) { - GL_CALL(glVertexAttribPointerARB(kTexCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords)); - GL_CALL(glVertexAttribPointerARB(kPositionAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices)); - } else { -#endif - GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords)); - GL_CALL(glVertexPointer(2, GL_FLOAT, 0, vertices)); -#if !USE_FORCED_GLES - } -#endif -#endif -#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - } -#endif + // Setup coordinates for drawing. + g_context.setDrawCoordinates(vertices, texcoords); // Draw the texture to the screen buffer. GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); -- cgit v1.2.3 From b081fe63e866883b424dfefb694c9b6518efa3b4 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 2 Jan 2016 02:15:20 +0100 Subject: OPENGL: Create new abstraction for GL texture objects. --- backends/graphics/opengl/texture.cpp | 212 ++++++++++++++++++++++------------- 1 file changed, 132 insertions(+), 80 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 08f5e69f03..656de20f25 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -40,87 +40,171 @@ static GLuint nextHigher2(GLuint v) { return ++v; } -GLint Texture::_maxTextureSize = 0; -void Texture::queryTextureInformation() { - GL_CALL(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_maxTextureSize)); - debug(5, "OpenGL maximum texture size: %d", _maxTextureSize); +GLTexture::GLTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType) + : _glIntFormat(glIntFormat), _glFormat(glFormat), _glType(glType), + _width(0), _height(0), _texCoords(), _glFilter(GL_NEAREST), + _glTexture(0) { + create(); } -Texture::Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format) - : _glIntFormat(glIntFormat), _glFormat(glFormat), _glType(glType), _format(format), _glFilter(GL_NEAREST), - _glTexture(0), _textureData(), _userPixelData(), _allDirty(false) { - recreateInternalTexture(); +GLTexture::~GLTexture() { + GL_CALL_SAFE(glDeleteTextures, (1, &_glTexture)); } -Texture::~Texture() { - GL_CALL_SAFE(glDeleteTextures, (1, &_glTexture)); - _textureData.free(); +void GLTexture::enableLinearFiltering(bool enable) { + if (enable) { + _glFilter = GL_LINEAR; + } else { + _glFilter = GL_NEAREST; + } + + bind(); + + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter)); } -void Texture::releaseInternalTexture() { +void GLTexture::destroy() { GL_CALL(glDeleteTextures(1, &_glTexture)); _glTexture = 0; } -void Texture::recreateInternalTexture() { +void GLTexture::create() { // Release old texture name in case it exists. - releaseInternalTexture(); + destroy(); // Get a new texture name. GL_CALL(glGenTextures(1, &_glTexture)); // Set up all texture parameters. - GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + bind(); GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter)); GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter)); GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - // In case there is an actual texture setup we reinitialize it. - if (_textureData.getPixels()) { + // If a size is specified, allocate memory for it. + if (_width != 0 && _height != 0) { // Allocate storage for OpenGL texture. - GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w, - _textureData.h, 0, _glFormat, _glType, NULL)); - - // Mark dirts such that it will be completely refreshed the next time. - flagDirty(); + GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _width, _height, + 0, _glFormat, _glType, NULL)); } } -void Texture::enableLinearFiltering(bool enable) { - if (enable) { - _glFilter = GL_LINEAR; +void GLTexture::bind() { + GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); +} + +void GLTexture::setSize(uint width, uint height) { + const uint oldWidth = _width; + const uint oldHeight = _height; + + if (!g_context.NPOTSupported) { + _width = nextHigher2(width); + _height = nextHigher2(height); } else { - _glFilter = GL_NEAREST; + _width = width; + _height = height; } - GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + // If a size is specified, allocate memory for it. + if (width != 0 && height != 0) { + const GLfloat texWidth = (GLfloat)width / _width; + const GLfloat texHeight = (GLfloat)height / _height; - GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter)); - GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter)); + _texCoords[0] = 0; + _texCoords[1] = 0; + + _texCoords[2] = texWidth; + _texCoords[3] = 0; + + _texCoords[4] = 0; + _texCoords[5] = texHeight; + + _texCoords[6] = texWidth; + _texCoords[7] = texHeight; + + // Allocate storage for OpenGL texture if necessary. + if (oldWidth != _width || oldHeight != _height) { + bind(); + GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _width, + _height, 0, _glFormat, _glType, NULL)); + } + } } -void Texture::allocate(uint width, uint height) { - uint texWidth = width, texHeight = height; - if (!g_context.NPOTSupported) { - texWidth = nextHigher2(texWidth); - texHeight = nextHigher2(texHeight); +void GLTexture::updateArea(const Common::Rect &area, const Graphics::Surface &src) { + // Set the texture on the active texture unit. + bind(); + + // Update the actual texture. + // Although we have the area of the texture buffer we want to update we + // cannot take advantage of the left/right boundries here because it is + // not possible to specify a pitch to glTexSubImage2D. To be precise, with + // plain OpenGL we could set GL_UNPACK_ROW_LENGTH to achieve this. However, + // OpenGL ES 1.0 does not support GL_UNPACK_ROW_LENGTH. Thus, we are left + // with the following options: + // + // 1) (As we do right now) Simply always update the whole texture lines of + // rect changed. This is simplest to implement. In case performance is + // really an issue we can think of switching to another method. + // + // 2) Copy the dirty rect to a temporary buffer and upload that by using + // glTexSubImage2D. This is what the Android backend does. It is more + // complicated though. + // + // 3) Use glTexSubImage2D per line changed. This is what the old OpenGL + // graphics manager did but it is much slower! Thus, we do not use it. + GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, area.top, src.w, area.height(), + _glFormat, _glType, src.getBasePtr(0, area.top))); +} + +GLint Texture::_maxTextureSize = 0; + +void Texture::queryTextureInformation() { + GL_CALL(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_maxTextureSize)); + debug(5, "OpenGL maximum texture size: %d", _maxTextureSize); +} + +Texture::Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format) + : _format(format), _glTexture(glIntFormat, glFormat, glType), + _textureData(), _userPixelData(), _allDirty(false) { + recreateInternalTexture(); +} + +Texture::~Texture() { + _textureData.free(); +} + +void Texture::releaseInternalTexture() { + _glTexture.destroy(); +} + +void Texture::recreateInternalTexture() { + _glTexture.create(); + + // In case image date exists assure it will be completely refreshed next + // time. + if (_textureData.getPixels()) { + flagDirty(); } +} - // In case the needed texture dimension changed we will reinitialize the - // texture. - if (texWidth != _textureData.w || texHeight != _textureData.h) { - // Create a buffer for the texture data. - _textureData.create(texWidth, texHeight, _format); +void Texture::enableLinearFiltering(bool enable) { + _glTexture.enableLinearFiltering(enable); +} - // Set the texture. - GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); +void Texture::allocate(uint width, uint height) { + // Assure the texture can contain our user data. + _glTexture.setSize(width, height); - // Allocate storage for OpenGL texture. - GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w, - _textureData.h, 0, _glFormat, _glType, NULL)); + // In case the needed texture dimension changed we will reinitialize the + // texture data buffer. + if (_glTexture.getWidth() != _textureData.w || _glTexture.getHeight() != _textureData.h) { + // Create a buffer for the texture data. + _textureData.create(_glTexture.getWidth(), _glTexture.getHeight(), _format); } // Create a sub-buffer for raw access. @@ -175,17 +259,7 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { updateTexture(); // Set the texture. - GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); - - // Calculate the texture rect that will be drawn. - const GLfloat texWidth = (GLfloat)_userPixelData.w / _textureData.w; - const GLfloat texHeight = (GLfloat)_userPixelData.h / _textureData.h; - const GLfloat texcoords[4*2] = { - 0, 0, - texWidth, 0, - 0, texHeight, - texWidth, texHeight - }; + _glTexture.bind(); // Calculate the screen rect where the texture will be drawn. const GLfloat vertices[4*2] = { @@ -196,7 +270,7 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { }; // Setup coordinates for drawing. - g_context.setDrawCoordinates(vertices, texcoords); + g_context.setDrawCoordinates(vertices, _glTexture.getTexCoords()); // Draw the texture to the screen buffer. GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); @@ -211,7 +285,7 @@ void Texture::updateTexture() { // In case we use linear filtering we might need to duplicate the last // pixel row/column to avoid glitches with filtering. - if (_glFilter == GL_LINEAR) { + if (_glTexture.isLinearFilteringEnabled()) { if (dirtyArea.right == _userPixelData.w && _userPixelData.w != _textureData.w) { uint height = dirtyArea.height(); @@ -238,29 +312,7 @@ void Texture::updateTexture() { } } - // Set the texture. - GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); - - // Update the actual texture. - // Although we keep track of the dirty part of the texture buffer we - // cannot take advantage of the left/right boundries here because it is - // not possible to specify a pitch to glTexSubImage2D. To be precise, with - // plain OpenGL we could set GL_UNPACK_ROW_LENGTH to achieve this. However, - // OpenGL ES 1.0 does not support GL_UNPACK_ROW_LENGTH. Thus, we are left - // with the following options: - // - // 1) (As we do right now) Simply always update the whole texture lines of - // rect changed. This is simplest to implement. In case performance is - // really an issue we can think of switching to another method. - // - // 2) Copy the dirty rect to a temporary buffer and upload that by using - // glTexSubImage2D. This is what the Android backend does. It is more - // complicated though. - // - // 3) Use glTexSubImage2D per line changed. This is what the old OpenGL - // graphics manager did but it is much slower! Thus, we do not use it. - GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, dirtyArea.top, _textureData.w, dirtyArea.height(), - _glFormat, _glType, _textureData.getBasePtr(0, dirtyArea.top))); + _glTexture.updateArea(dirtyArea, _textureData); // We should have handled everything, thus not dirty anymore. clearDirty(); -- cgit v1.2.3 From 9844d89231de0fc2234199620390dbd057e79103 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 2 Jan 2016 02:20:28 +0100 Subject: OPENGL: Move max texture size information to Context. --- backends/graphics/opengl/texture.cpp | 7 ------- 1 file changed, 7 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 656de20f25..da4ebeb1e4 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -161,13 +161,6 @@ void GLTexture::updateArea(const Common::Rect &area, const Graphics::Surface &sr _glFormat, _glType, src.getBasePtr(0, area.top))); } -GLint Texture::_maxTextureSize = 0; - -void Texture::queryTextureInformation() { - GL_CALL(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_maxTextureSize)); - debug(5, "OpenGL maximum texture size: %d", _maxTextureSize); -} - Texture::Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format) : _format(format), _glTexture(glIntFormat, glFormat, glType), _textureData(), _userPixelData(), _allDirty(false) { -- cgit v1.2.3 From 618adec7b06546e81028cb9fcce6151cb388fe98 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 2 Jan 2016 05:06:32 +0100 Subject: OPENGL: Move color key handling for CLUT8 to TextureCLUT8. --- backends/graphics/opengl/texture.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index da4ebeb1e4..a607528915 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -346,6 +346,26 @@ Graphics::PixelFormat TextureCLUT8::getFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } +void TextureCLUT8::setColorKey(uint colorKey) { + // We remove all alpha bits from the palette entry of the color key. + // This makes sure its properly handled as color key. + const Graphics::PixelFormat &hardwareFormat = getHardwareFormat(); + const uint32 aMask = (0xFF >> hardwareFormat.aLoss) << hardwareFormat.aShift; + + if (hardwareFormat.bytesPerPixel == 2) { + uint16 *palette = (uint16 *)_palette + colorKey; + *palette &= ~aMask; + } else if (hardwareFormat.bytesPerPixel == 4) { + uint32 *palette = (uint32 *)_palette + colorKey; + *palette &= ~aMask; + } else { + warning("TextureCLUT8::setColorKey: Unsupported pixel depth %d", hardwareFormat.bytesPerPixel); + } + + // A palette changes means we need to refresh the whole surface. + flagDirty(); +} + namespace { template inline void convertPalette(ColorType *dst, const byte *src, uint colors, const Graphics::PixelFormat &format) { -- cgit v1.2.3 From 8b0cf0c5f7aa34e88a7702c4e9f54f5d8adc5ab8 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 2 Jan 2016 05:15:34 +0100 Subject: OPENGL: Cleanup. Remove Texture::getHardwareFormat. --- backends/graphics/opengl/texture.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index a607528915..0411df3ee1 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -349,17 +349,16 @@ Graphics::PixelFormat TextureCLUT8::getFormat() const { void TextureCLUT8::setColorKey(uint colorKey) { // We remove all alpha bits from the palette entry of the color key. // This makes sure its properly handled as color key. - const Graphics::PixelFormat &hardwareFormat = getHardwareFormat(); - const uint32 aMask = (0xFF >> hardwareFormat.aLoss) << hardwareFormat.aShift; + const uint32 aMask = (0xFF >> _format.aLoss) << _format.aShift; - if (hardwareFormat.bytesPerPixel == 2) { + if (_format.bytesPerPixel == 2) { uint16 *palette = (uint16 *)_palette + colorKey; *palette &= ~aMask; - } else if (hardwareFormat.bytesPerPixel == 4) { + } else if (_format.bytesPerPixel == 4) { uint32 *palette = (uint32 *)_palette + colorKey; *palette &= ~aMask; } else { - warning("TextureCLUT8::setColorKey: Unsupported pixel depth %d", hardwareFormat.bytesPerPixel); + warning("TextureCLUT8::setColorKey: Unsupported pixel depth %d", _format.bytesPerPixel); } // A palette changes means we need to refresh the whole surface. @@ -377,14 +376,12 @@ inline void convertPalette(ColorType *dst, const byte *src, uint colors, const G } // End of anonymous namespace void TextureCLUT8::setPalette(uint start, uint colors, const byte *palData) { - const Graphics::PixelFormat &hardwareFormat = getHardwareFormat(); - - if (hardwareFormat.bytesPerPixel == 2) { - convertPalette((uint16 *)_palette + start, palData, colors, hardwareFormat); - } else if (hardwareFormat.bytesPerPixel == 4) { - convertPalette((uint32 *)_palette + start, palData, colors, hardwareFormat); + if (_format.bytesPerPixel == 2) { + convertPalette((uint16 *)_palette + start, palData, colors, _format); + } else if (_format.bytesPerPixel == 4) { + convertPalette((uint32 *)_palette + start, palData, colors, _format); } else { - warning("TextureCLUT8::setPalette: Unsupported pixel depth: %d", hardwareFormat.bytesPerPixel); + warning("TextureCLUT8::setPalette: Unsupported pixel depth: %d", _format.bytesPerPixel); } // A palette changes means we need to refresh the whole surface. -- cgit v1.2.3 From de3846923c9a00ff6a8563e33858e12a72bfebda Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 2 Jan 2016 05:54:08 +0100 Subject: OPENGL: Introduce simple abstraction for surfaces. This is basically an interface extracted from Texture without any knowledge about any actual implementation, except for copyRectToTexture, fill, and dirty rect handling. These are convenient helpers. --- backends/graphics/opengl/texture.cpp | 111 +++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 50 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 0411df3ee1..e9713eeb40 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -161,50 +161,15 @@ void GLTexture::updateArea(const Common::Rect &area, const Graphics::Surface &sr _glFormat, _glType, src.getBasePtr(0, area.top))); } -Texture::Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format) - : _format(format), _glTexture(glIntFormat, glFormat, glType), - _textureData(), _userPixelData(), _allDirty(false) { - recreateInternalTexture(); -} - -Texture::~Texture() { - _textureData.free(); -} - -void Texture::releaseInternalTexture() { - _glTexture.destroy(); -} - -void Texture::recreateInternalTexture() { - _glTexture.create(); +// +// Surface +// - // In case image date exists assure it will be completely refreshed next - // time. - if (_textureData.getPixels()) { - flagDirty(); - } +Surface::Surface() + : _allDirty(false), _dirtyArea() { } -void Texture::enableLinearFiltering(bool enable) { - _glTexture.enableLinearFiltering(enable); -} - -void Texture::allocate(uint width, uint height) { - // Assure the texture can contain our user data. - _glTexture.setSize(width, height); - - // In case the needed texture dimension changed we will reinitialize the - // texture data buffer. - if (_glTexture.getWidth() != _textureData.w || _glTexture.getHeight() != _textureData.h) { - // Create a buffer for the texture data. - _textureData.create(_glTexture.getWidth(), _glTexture.getHeight(), _format); - } - - // Create a sub-buffer for raw access. - _userPixelData = _textureData.getSubArea(Common::Rect(width, height)); -} - -void Texture::copyRectToTexture(uint x, uint y, uint w, uint h, const void *srcPtr, uint srcPitch) { +void Surface::copyRectToTexture(uint x, uint y, uint w, uint h, const void *srcPtr, uint srcPitch) { Graphics::Surface *dstSurf = getSurface(); assert(x + w <= dstSurf->w); assert(y + h <= dstSurf->h); @@ -235,13 +200,67 @@ void Texture::copyRectToTexture(uint x, uint y, uint w, uint h, const void *srcP } } -void Texture::fill(uint32 color) { +void Surface::fill(uint32 color) { Graphics::Surface *dst = getSurface(); dst->fillRect(Common::Rect(dst->w, dst->h), color); flagDirty(); } +Common::Rect Surface::getDirtyArea() const { + if (_allDirty) { + return Common::Rect(getWidth(), getHeight()); + } else { + return _dirtyArea; + } +} + +// +// Surface implementations +// + +Texture::Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format) + : Surface(), _format(format), _glTexture(glIntFormat, glFormat, glType), + _textureData(), _userPixelData() { +} + +Texture::~Texture() { + _textureData.free(); +} + +void Texture::destroy() { + _glTexture.destroy(); +} + +void Texture::recreate() { + _glTexture.create(); + + // In case image date exists assure it will be completely refreshed next + // time. + if (_textureData.getPixels()) { + flagDirty(); + } +} + +void Texture::enableLinearFiltering(bool enable) { + _glTexture.enableLinearFiltering(enable); +} + +void Texture::allocate(uint width, uint height) { + // Assure the texture can contain our user data. + _glTexture.setSize(width, height); + + // In case the needed texture dimension changed we will reinitialize the + // texture data buffer. + if (_glTexture.getWidth() != _textureData.w || _glTexture.getHeight() != _textureData.h) { + // Create a buffer for the texture data. + _textureData.create(_glTexture.getWidth(), _glTexture.getHeight(), _format); + } + + // Create a sub-buffer for raw access. + _userPixelData = _textureData.getSubArea(Common::Rect(width, height)); +} + void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { // Only do any processing when the Texture is initialized. if (!_textureData.getPixels()) { @@ -311,14 +330,6 @@ void Texture::updateTexture() { clearDirty(); } -Common::Rect Texture::getDirtyArea() const { - if (_allDirty) { - return Common::Rect(_userPixelData.w, _userPixelData.h); - } else { - return _dirtyArea; - } -} - TextureCLUT8::TextureCLUT8(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format) : Texture(glIntFormat, glFormat, glType, format), _clut8Data(), _palette(new byte[256 * format.bytesPerPixel]) { memset(_palette, 0, sizeof(byte) * format.bytesPerPixel); -- cgit v1.2.3 From e66e9e44d358b0cc90d128c31e695a8ace4177fa Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 2 Jan 2016 14:09:41 +0100 Subject: OPENGL: Accelerate palette lookups with shaders. This currently is limited to GL contexts. --- backends/graphics/opengl/texture.cpp | 270 +++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index e9713eeb40..5ae4987874 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -504,4 +504,274 @@ void TextureRGB555::updateTexture() { } #endif // !USE_FORCED_GL +#if !USE_FORCED_GLES && !USE_FORCED_GLES2 +namespace { +const char *const g_lookUpFragmentShaderGL = + "varying vec2 texCoord;\n" + "varying vec4 blendColor;\n" + "\n" + "uniform sampler2D texture;\n" + "uniform sampler2D palette;\n" + "\n" + "const float adjustFactor = 255.0 / 256.0 + 1.0 / (2.0 * 256.0);" + "\n" + "void main(void) {\n" + "\tvec4 index = texture2D(texture, texCoord);\n" + "\tgl_FragColor = blendColor * texture2D(palette, vec2(index.x * adjustFactor, 0.0));\n" + "}\n"; +} // End of anonymous namespace + +TextureCLUT8GPU::TextureCLUT8GPU() + : _clut8Texture(GL_R8, GL_RED, GL_UNSIGNED_BYTE), + _paletteTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE), + _glTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE), + _glFBO(0), _clut8Vertices(), _projectionMatrix(), + _lookUpShader(nullptr), _paletteLocation(-1), + _clut8Data(), _userPixelData(), _palette(), _paletteDirty(false) { + // Allocate space for 256 colors. + _paletteTexture.setSize(256, 1); + + _lookUpShader = new Shader(g_defaultVertexShader, g_lookUpFragmentShaderGL); + _lookUpShader->recreate(); + _paletteLocation = _lookUpShader->getUniformLocation("palette"); + + setupFBO(); +} + +TextureCLUT8GPU::~TextureCLUT8GPU() { + delete _lookUpShader; + GL_CALL_SAFE(glDeleteFramebuffers, (1, &_glFBO)); + _clut8Data.free(); +} + +void TextureCLUT8GPU::destroy() { + _clut8Texture.destroy(); + _paletteTexture.destroy(); + _glTexture.destroy(); + _lookUpShader->destroy(); + + GL_CALL(glDeleteFramebuffers(1, &_glFBO)); + _glFBO = 0; +} + +void TextureCLUT8GPU::recreate() { + _clut8Texture.create(); + _paletteTexture.create(); + _glTexture.create(); + _lookUpShader->recreate(); + _paletteLocation = _lookUpShader->getUniformLocation("palette"); + setupFBO(); + + // In case image date exists assure it will be completely refreshed next + // time. + if (_clut8Data.getPixels()) { + flagDirty(); + _paletteDirty = true; + } +} + +void TextureCLUT8GPU::enableLinearFiltering(bool enable) { + _glTexture.enableLinearFiltering(enable); +} + +void TextureCLUT8GPU::allocate(uint width, uint height) { + // Assure the texture can contain our user data. + _clut8Texture.setSize(width, height); + _glTexture.setSize(width, height); + + // In case the needed texture dimension changed we will reinitialize the + // texture data buffer. + if (_clut8Texture.getWidth() != _clut8Data.w || _clut8Texture.getHeight() != _clut8Data.h) { + // Create a buffer for the texture data. + _clut8Data.create(_clut8Texture.getWidth(), _clut8Texture.getHeight(), Graphics::PixelFormat::createFormatCLUT8()); + } + + // Create a sub-buffer for raw access. + _userPixelData = _clut8Data.getSubArea(Common::Rect(width, height)); + + // Setup structures for internal rendering to _glTexture. + _clut8Vertices[0] = 0; + _clut8Vertices[1] = 0; + + _clut8Vertices[2] = width; + _clut8Vertices[3] = 0; + + _clut8Vertices[4] = 0; + _clut8Vertices[5] = height; + + _clut8Vertices[6] = width; + _clut8Vertices[7] = height; + + _projectionMatrix[ 0] = 2.0f / _glTexture.getWidth(); + _projectionMatrix[ 1] = 0.0f; + _projectionMatrix[ 2] = 0.0f; + _projectionMatrix[ 3] = 0.0f; + + _projectionMatrix[ 4] = 0.0f; + _projectionMatrix[ 5] = 2.0f / _glTexture.getHeight(); + _projectionMatrix[ 6] = 0.0f; + _projectionMatrix[ 7] = 0.0f; + + _projectionMatrix[ 8] = 0.0f; + _projectionMatrix[ 9] = 0.0f; + _projectionMatrix[10] = 0.0f; + _projectionMatrix[11] = 0.0f; + + _projectionMatrix[12] = -1.0f; + _projectionMatrix[13] = -1.0f; + _projectionMatrix[14] = 0.0f; + _projectionMatrix[15] = 1.0f; +} + +void TextureCLUT8GPU::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { + // Only do any processing when the Texture is initialized. + if (!_clut8Data.getPixels()) { + return; + } + + // First update any potentional changes. + updateTextures(); + + // Set the texture. + _glTexture.bind(); + + // Calculate the screen rect where the texture will be drawn. + const GLfloat vertices[4*2] = { + x, y, + x + w, y, + x, y + h, + x + w, y + h + }; + + // Setup coordinates for drawing. + g_context.setDrawCoordinates(vertices, _glTexture.getTexCoords()); + + // Draw the texture to the screen buffer. + GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); +} + +Graphics::PixelFormat TextureCLUT8GPU::getFormat() const { + return Graphics::PixelFormat::createFormatCLUT8(); +} + +void TextureCLUT8GPU::setColorKey(uint colorKey) { + _palette[colorKey * 4 + 3] = 0x00; + + _paletteDirty = true; +} + +void TextureCLUT8GPU::setPalette(uint start, uint colors, const byte *palData) { + byte *dst = _palette + start * 4; + + while (colors-- > 0) { + memcpy(dst, palData, 3); + dst[3] = 0xFF; + + dst += 4; + palData += 3; + } + + _paletteDirty = true; +} + +void TextureCLUT8GPU::updateTextures() { + const bool needLookUp = Surface::isDirty() || _paletteDirty; + + // Update CLUT8 texture if necessary. + if (Surface::isDirty()) { + _clut8Texture.updateArea(getDirtyArea(), _clut8Data); + clearDirty(); + } + + // Update palette if necessary. + if (_paletteDirty) { + Graphics::Surface palSurface; + palSurface.init(256, 1, 256, _palette, +#ifdef SCUMM_LITTLE_ENDIAN + Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24) // ABGR8888 +#else + Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0) // RGBA8888 +#endif + ); + + _paletteTexture.updateArea(Common::Rect(256, 1), palSurface); + _paletteDirty = false; + } + + // In case any data changed, do color look up and save result in _glTexture. + if (needLookUp) { + lookUpColors(); + } +} + +void TextureCLUT8GPU::lookUpColors() { + // Save old state. + GLint oldProgram = 0; + GL_CALL(glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram)); + + GLint viewport[4]; + GL_CALL(glGetIntegerv(GL_VIEWPORT, viewport)); + + GLboolean scissorState; + GL_ASSIGN(scissorState, glIsEnabled(GL_SCISSOR_TEST)); + GLboolean blendState; + GL_ASSIGN(blendState, glIsEnabled(GL_BLEND)); + + GLint oldFBO = 0; + GL_CALL(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFBO)); + + // Update state. + GL_CALL(glViewport(0, 0, _glTexture.getWidth(), _glTexture.getHeight())); + GL_CALL(glDisable(GL_SCISSOR_TEST)); + GL_CALL(glDisable(GL_BLEND)); + + // Bind framebuffer. + GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, _glFBO)); + + // Set the palette texture. + GL_CALL(glActiveTexture(GL_TEXTURE1)); + _paletteTexture.bind(); + + // Set the clut8 texture. + GL_CALL(glActiveTexture(GL_TEXTURE0)); + _clut8Texture.bind(); + + // Do color look up. + _lookUpShader->activate(_projectionMatrix); + _lookUpShader->setUniformI(_paletteLocation, 1); + g_context.setDrawCoordinates(_clut8Vertices, _clut8Texture.getTexCoords()); + GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); + + // Restore old state. + GL_CALL(glUseProgram(oldProgram)); + GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, oldFBO)); + + if (blendState) { + GL_CALL(glEnable(GL_BLEND)); + } + if (scissorState) { + GL_CALL(glEnable(GL_SCISSOR_TEST)); + } + GL_CALL(glViewport(viewport[0], viewport[1], viewport[2], viewport[3])); +} + +void TextureCLUT8GPU::setupFBO() { + // Allocate framebuffer object if necessary. + if (!_glFBO) { + GL_CALL(glGenFramebuffers(1, &_glFBO)); + } + + // Save old FBO. + GLint oldFBO = 0; + GL_CALL(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFBO)); + + // Attach destination texture to FBO. + GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, _glFBO)); + GL_CALL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _glTexture.getGLTexture(), 0)); + + // Restore old FBO. + GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, oldFBO)); +} +#endif // !USE_FORCED_GLES && !USE_FORCED_GLES2 + } // End of namespace OpenGL -- cgit v1.2.3 From 08553a09cfa2110d56b200bf6c69d01d5adbc6bb Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 3 Jan 2016 14:06:02 +0100 Subject: OPENGL: Support GLSL based CLUT8 look up for GLES2+. --- backends/graphics/opengl/texture.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 5ae4987874..f98bf8be06 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -504,9 +504,9 @@ void TextureRGB555::updateTexture() { } #endif // !USE_FORCED_GL -#if !USE_FORCED_GLES && !USE_FORCED_GLES2 +#if !USE_FORCED_GLES namespace { -const char *const g_lookUpFragmentShaderGL = +const char *const g_lookUpFragmentShader = "varying vec2 texCoord;\n" "varying vec4 blendColor;\n" "\n" @@ -517,12 +517,17 @@ const char *const g_lookUpFragmentShaderGL = "\n" "void main(void) {\n" "\tvec4 index = texture2D(texture, texCoord);\n" - "\tgl_FragColor = blendColor * texture2D(palette, vec2(index.x * adjustFactor, 0.0));\n" + "\tgl_FragColor = blendColor * texture2D(palette, vec2(index.a * adjustFactor, 0.0));\n" "}\n"; } // End of anonymous namespace +// _clut8Texture needs 8 bits internal precision, otherwise graphics glitches +// can occur. GL_ALPHA does not have any internal precision requirements. +// However, in practice (according to fuzzie) it's 8bit. If we run into +// problems, we need to switch to GL_R8 and GL_RED, but that is only supported +// for ARB_texture_rg and GLES3+ (EXT_rexture_rg does not support GL_R8). TextureCLUT8GPU::TextureCLUT8GPU() - : _clut8Texture(GL_R8, GL_RED, GL_UNSIGNED_BYTE), + : _clut8Texture(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE), _paletteTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE), _glTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE), _glFBO(0), _clut8Vertices(), _projectionMatrix(), @@ -531,7 +536,7 @@ TextureCLUT8GPU::TextureCLUT8GPU() // Allocate space for 256 colors. _paletteTexture.setSize(256, 1); - _lookUpShader = new Shader(g_defaultVertexShader, g_lookUpFragmentShaderGL); + _lookUpShader = new Shader(g_defaultVertexShader, g_lookUpFragmentShader); _lookUpShader->recreate(); _paletteLocation = _lookUpShader->getUniformLocation("palette"); @@ -772,6 +777,6 @@ void TextureCLUT8GPU::setupFBO() { // Restore old FBO. GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, oldFBO)); } -#endif // !USE_FORCED_GLES && !USE_FORCED_GLES2 +#endif // !USE_FORCED_GLES } // End of namespace OpenGL -- cgit v1.2.3 From f5f1b6eba0d409abcda2a3c037a177d6f6e41a2e Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 4 Jan 2016 06:41:10 +0100 Subject: OPENGL: Introduce pipeline abstraction to cleanup code. --- backends/graphics/opengl/texture.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index f98bf8be06..61e8dc37b3 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -22,6 +22,7 @@ #include "backends/graphics/opengl/texture.h" #include "backends/graphics/opengl/shader.h" +#include "backends/graphics/opengl/pipeline.h" #include "common/rect.h" #include "common/textconsole.h" @@ -282,7 +283,7 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { }; // Setup coordinates for drawing. - g_context.setDrawCoordinates(vertices, _glTexture.getTexCoords()); + g_context.activePipeline->setDrawCoordinates(vertices, _glTexture.getTexCoords()); // Draw the texture to the screen buffer. GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); @@ -649,7 +650,7 @@ void TextureCLUT8GPU::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { }; // Setup coordinates for drawing. - g_context.setDrawCoordinates(vertices, _glTexture.getTexCoords()); + g_context.activePipeline->setDrawCoordinates(vertices, _glTexture.getTexCoords()); // Draw the texture to the screen buffer. GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); @@ -744,7 +745,7 @@ void TextureCLUT8GPU::lookUpColors() { // Do color look up. _lookUpShader->activate(_projectionMatrix); _lookUpShader->setUniformI(_paletteLocation, 1); - g_context.setDrawCoordinates(_clut8Vertices, _clut8Texture.getTexCoords()); + g_context.activePipeline->setDrawCoordinates(_clut8Vertices, _clut8Texture.getTexCoords()); GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); // Restore old state. -- cgit v1.2.3 From 5498982a3754edccb498521587c553e0ecbe7328 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 4 Jan 2016 07:07:37 +0100 Subject: OPENGL: Introduce ShaderManager to handle builtin shaders. --- backends/graphics/opengl/texture.cpp | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 61e8dc37b3..828dade0be 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -506,21 +506,6 @@ void TextureRGB555::updateTexture() { #endif // !USE_FORCED_GL #if !USE_FORCED_GLES -namespace { -const char *const g_lookUpFragmentShader = - "varying vec2 texCoord;\n" - "varying vec4 blendColor;\n" - "\n" - "uniform sampler2D texture;\n" - "uniform sampler2D palette;\n" - "\n" - "const float adjustFactor = 255.0 / 256.0 + 1.0 / (2.0 * 256.0);" - "\n" - "void main(void) {\n" - "\tvec4 index = texture2D(texture, texCoord);\n" - "\tgl_FragColor = blendColor * texture2D(palette, vec2(index.a * adjustFactor, 0.0));\n" - "}\n"; -} // End of anonymous namespace // _clut8Texture needs 8 bits internal precision, otherwise graphics glitches // can occur. GL_ALPHA does not have any internal precision requirements. @@ -532,20 +517,17 @@ TextureCLUT8GPU::TextureCLUT8GPU() _paletteTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE), _glTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE), _glFBO(0), _clut8Vertices(), _projectionMatrix(), - _lookUpShader(nullptr), _paletteLocation(-1), + _paletteLocation(-1), _clut8Data(), _userPixelData(), _palette(), _paletteDirty(false) { // Allocate space for 256 colors. _paletteTexture.setSize(256, 1); - _lookUpShader = new Shader(g_defaultVertexShader, g_lookUpFragmentShader); - _lookUpShader->recreate(); - _paletteLocation = _lookUpShader->getUniformLocation("palette"); + _paletteLocation = ShaderMan.query(ShaderManager::kCLUT8LookUp)->getUniformLocation("palette"); setupFBO(); } TextureCLUT8GPU::~TextureCLUT8GPU() { - delete _lookUpShader; GL_CALL_SAFE(glDeleteFramebuffers, (1, &_glFBO)); _clut8Data.free(); } @@ -554,7 +536,6 @@ void TextureCLUT8GPU::destroy() { _clut8Texture.destroy(); _paletteTexture.destroy(); _glTexture.destroy(); - _lookUpShader->destroy(); GL_CALL(glDeleteFramebuffers(1, &_glFBO)); _glFBO = 0; @@ -564,8 +545,7 @@ void TextureCLUT8GPU::recreate() { _clut8Texture.create(); _paletteTexture.create(); _glTexture.create(); - _lookUpShader->recreate(); - _paletteLocation = _lookUpShader->getUniformLocation("palette"); + _paletteLocation = ShaderMan.query(ShaderManager::kCLUT8LookUp)->getUniformLocation("palette"); setupFBO(); // In case image date exists assure it will be completely refreshed next @@ -743,8 +723,9 @@ void TextureCLUT8GPU::lookUpColors() { _clut8Texture.bind(); // Do color look up. - _lookUpShader->activate(_projectionMatrix); - _lookUpShader->setUniformI(_paletteLocation, 1); + Shader *lookUpShader = ShaderMan.query(ShaderManager::kCLUT8LookUp); + lookUpShader->activate(_projectionMatrix); + lookUpShader->setUniformI(_paletteLocation, 1); g_context.activePipeline->setDrawCoordinates(_clut8Vertices, _clut8Texture.getTexCoords()); GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); -- cgit v1.2.3 From c4e65732befdfb675111387c3c7edb616bf2f976 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 4 Jan 2016 10:18:15 +0100 Subject: OPENGL: Introduce abstraction for framebuffer. This allows us to use various framebuffer settings easily. Now the GPU accelerated CLUT8 surface implementation does not need to query former framebuffer state anymore. --- backends/graphics/opengl/texture.cpp | 95 +++++------------------------------- 1 file changed, 13 insertions(+), 82 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 828dade0be..02e1b2c325 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -23,6 +23,7 @@ #include "backends/graphics/opengl/texture.h" #include "backends/graphics/opengl/shader.h" #include "backends/graphics/opengl/pipeline.h" +#include "backends/graphics/opengl/framebuffer.h" #include "common/rect.h" #include "common/textconsole.h" @@ -515,38 +516,30 @@ void TextureRGB555::updateTexture() { TextureCLUT8GPU::TextureCLUT8GPU() : _clut8Texture(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE), _paletteTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE), - _glTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE), - _glFBO(0), _clut8Vertices(), _projectionMatrix(), - _paletteLocation(-1), + _target(new TextureTarget()), _clut8Vertices(), _paletteLocation(-1), _clut8Data(), _userPixelData(), _palette(), _paletteDirty(false) { // Allocate space for 256 colors. _paletteTexture.setSize(256, 1); _paletteLocation = ShaderMan.query(ShaderManager::kCLUT8LookUp)->getUniformLocation("palette"); - - setupFBO(); } TextureCLUT8GPU::~TextureCLUT8GPU() { - GL_CALL_SAFE(glDeleteFramebuffers, (1, &_glFBO)); + delete _target; _clut8Data.free(); } void TextureCLUT8GPU::destroy() { _clut8Texture.destroy(); _paletteTexture.destroy(); - _glTexture.destroy(); - - GL_CALL(glDeleteFramebuffers(1, &_glFBO)); - _glFBO = 0; + _target->destroy(); } void TextureCLUT8GPU::recreate() { _clut8Texture.create(); _paletteTexture.create(); - _glTexture.create(); _paletteLocation = ShaderMan.query(ShaderManager::kCLUT8LookUp)->getUniformLocation("palette"); - setupFBO(); + _target->create(); // In case image date exists assure it will be completely refreshed next // time. @@ -557,13 +550,13 @@ void TextureCLUT8GPU::recreate() { } void TextureCLUT8GPU::enableLinearFiltering(bool enable) { - _glTexture.enableLinearFiltering(enable); + _target->getTexture()->enableLinearFiltering(enable); } void TextureCLUT8GPU::allocate(uint width, uint height) { // Assure the texture can contain our user data. _clut8Texture.setSize(width, height); - _glTexture.setSize(width, height); + _target->setSize(width, height); // In case the needed texture dimension changed we will reinitialize the // texture data buffer. @@ -587,26 +580,6 @@ void TextureCLUT8GPU::allocate(uint width, uint height) { _clut8Vertices[6] = width; _clut8Vertices[7] = height; - - _projectionMatrix[ 0] = 2.0f / _glTexture.getWidth(); - _projectionMatrix[ 1] = 0.0f; - _projectionMatrix[ 2] = 0.0f; - _projectionMatrix[ 3] = 0.0f; - - _projectionMatrix[ 4] = 0.0f; - _projectionMatrix[ 5] = 2.0f / _glTexture.getHeight(); - _projectionMatrix[ 6] = 0.0f; - _projectionMatrix[ 7] = 0.0f; - - _projectionMatrix[ 8] = 0.0f; - _projectionMatrix[ 9] = 0.0f; - _projectionMatrix[10] = 0.0f; - _projectionMatrix[11] = 0.0f; - - _projectionMatrix[12] = -1.0f; - _projectionMatrix[13] = -1.0f; - _projectionMatrix[14] = 0.0f; - _projectionMatrix[15] = 1.0f; } void TextureCLUT8GPU::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { @@ -619,7 +592,7 @@ void TextureCLUT8GPU::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { updateTextures(); // Set the texture. - _glTexture.bind(); + _target->getTexture()->bind(); // Calculate the screen rect where the texture will be drawn. const GLfloat vertices[4*2] = { @@ -630,7 +603,7 @@ void TextureCLUT8GPU::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { }; // Setup coordinates for drawing. - g_context.activePipeline->setDrawCoordinates(vertices, _glTexture.getTexCoords()); + g_context.activePipeline->setDrawCoordinates(vertices, _target->getTexture()->getTexCoords()); // Draw the texture to the screen buffer. GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); @@ -695,24 +668,7 @@ void TextureCLUT8GPU::lookUpColors() { GLint oldProgram = 0; GL_CALL(glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram)); - GLint viewport[4]; - GL_CALL(glGetIntegerv(GL_VIEWPORT, viewport)); - - GLboolean scissorState; - GL_ASSIGN(scissorState, glIsEnabled(GL_SCISSOR_TEST)); - GLboolean blendState; - GL_ASSIGN(blendState, glIsEnabled(GL_BLEND)); - - GLint oldFBO = 0; - GL_CALL(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFBO)); - - // Update state. - GL_CALL(glViewport(0, 0, _glTexture.getWidth(), _glTexture.getHeight())); - GL_CALL(glDisable(GL_SCISSOR_TEST)); - GL_CALL(glDisable(GL_BLEND)); - - // Bind framebuffer. - GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, _glFBO)); + Framebuffer *oldFramebuffer = g_context.setFramebuffer(_target); // Set the palette texture. GL_CALL(glActiveTexture(GL_TEXTURE1)); @@ -724,40 +680,15 @@ void TextureCLUT8GPU::lookUpColors() { // Do color look up. Shader *lookUpShader = ShaderMan.query(ShaderManager::kCLUT8LookUp); - lookUpShader->activate(_projectionMatrix); + lookUpShader->activate(_target->getProjectionMatrix()); lookUpShader->setUniformI(_paletteLocation, 1); g_context.activePipeline->setDrawCoordinates(_clut8Vertices, _clut8Texture.getTexCoords()); GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); // Restore old state. - GL_CALL(glUseProgram(oldProgram)); - GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, oldFBO)); + g_context.setFramebuffer(oldFramebuffer); - if (blendState) { - GL_CALL(glEnable(GL_BLEND)); - } - if (scissorState) { - GL_CALL(glEnable(GL_SCISSOR_TEST)); - } - GL_CALL(glViewport(viewport[0], viewport[1], viewport[2], viewport[3])); -} - -void TextureCLUT8GPU::setupFBO() { - // Allocate framebuffer object if necessary. - if (!_glFBO) { - GL_CALL(glGenFramebuffers(1, &_glFBO)); - } - - // Save old FBO. - GLint oldFBO = 0; - GL_CALL(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFBO)); - - // Attach destination texture to FBO. - GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, _glFBO)); - GL_CALL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _glTexture.getGLTexture(), 0)); - - // Restore old FBO. - GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, oldFBO)); + GL_CALL(glUseProgram(oldProgram)); } #endif // !USE_FORCED_GLES -- cgit v1.2.3 From 0fe580d10c6fb73a90eccb046c8dcbf84b062b16 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 4 Jan 2016 11:38:21 +0100 Subject: OPENGL: Make shader/framebuffer part of pipeline state. --- backends/graphics/opengl/texture.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 02e1b2c325..05b7ac1896 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -657,7 +657,7 @@ void TextureCLUT8GPU::updateTextures() { _paletteDirty = false; } - // In case any data changed, do color look up and save result in _glTexture. + // In case any data changed, do color look up and store result in _target. if (needLookUp) { lookUpColors(); } @@ -665,10 +665,11 @@ void TextureCLUT8GPU::updateTextures() { void TextureCLUT8GPU::lookUpColors() { // Save old state. - GLint oldProgram = 0; - GL_CALL(glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram)); + Framebuffer *oldFramebuffer = g_context.activePipeline->setFramebuffer(_target); - Framebuffer *oldFramebuffer = g_context.setFramebuffer(_target); + Shader *lookUpShader = ShaderMan.query(ShaderManager::kCLUT8LookUp); + Shader *oldShader = g_context.activePipeline->setShader(lookUpShader); + lookUpShader->setUniformI(_paletteLocation, 1); // Set the palette texture. GL_CALL(glActiveTexture(GL_TEXTURE1)); @@ -679,16 +680,12 @@ void TextureCLUT8GPU::lookUpColors() { _clut8Texture.bind(); // Do color look up. - Shader *lookUpShader = ShaderMan.query(ShaderManager::kCLUT8LookUp); - lookUpShader->activate(_target->getProjectionMatrix()); - lookUpShader->setUniformI(_paletteLocation, 1); g_context.activePipeline->setDrawCoordinates(_clut8Vertices, _clut8Texture.getTexCoords()); GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); // Restore old state. - g_context.setFramebuffer(oldFramebuffer); - - GL_CALL(glUseProgram(oldProgram)); + g_context.activePipeline->setShader(oldShader); + g_context.activePipeline->setFramebuffer(oldFramebuffer); } #endif // !USE_FORCED_GLES -- cgit v1.2.3 From b17c035642cc33ee614046be011bf8ad9f9db95d Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 6 Jan 2016 16:52:03 +0100 Subject: OPENGL: Implement texture drawing in Pipeline instead of Surface. --- backends/graphics/opengl/texture.cpp | 76 ++++++------------------------------ 1 file changed, 11 insertions(+), 65 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 05b7ac1896..8b38f85e9f 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -95,7 +95,7 @@ void GLTexture::create() { } } -void GLTexture::bind() { +void GLTexture::bind() const { GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); } @@ -263,34 +263,7 @@ void Texture::allocate(uint width, uint height) { _userPixelData = _textureData.getSubArea(Common::Rect(width, height)); } -void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { - // Only do any processing when the Texture is initialized. - if (!_textureData.getPixels()) { - return; - } - - // First update any potentional changes. - updateTexture(); - - // Set the texture. - _glTexture.bind(); - - // Calculate the screen rect where the texture will be drawn. - const GLfloat vertices[4*2] = { - x, y, - x + w, y, - x, y + h, - x + w, y + h - }; - - // Setup coordinates for drawing. - g_context.activePipeline->setDrawCoordinates(vertices, _glTexture.getTexCoords()); - - // Draw the texture to the screen buffer. - GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); -} - -void Texture::updateTexture() { +void Texture::updateGLTexture() { if (!isDirty()) { return; } @@ -418,7 +391,7 @@ inline void doPaletteLookUp(PixelType *dst, const byte *src, uint width, uint he } } // End of anonymous namespace -void TextureCLUT8::updateTexture() { +void TextureCLUT8::updateGLTexture() { if (!isDirty()) { return; } @@ -443,7 +416,7 @@ void TextureCLUT8::updateTexture() { } // Do generic handling of updating the texture. - Texture::updateTexture(); + Texture::updateGLTexture(); } #if !USE_FORCED_GL @@ -502,7 +475,7 @@ void TextureRGB555::updateTexture() { } // Do generic handling of updating the texture. - Texture::updateTexture(); + Texture::updateGLTexture(); } #endif // !USE_FORCED_GL @@ -582,33 +555,6 @@ void TextureCLUT8GPU::allocate(uint width, uint height) { _clut8Vertices[7] = height; } -void TextureCLUT8GPU::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { - // Only do any processing when the Texture is initialized. - if (!_clut8Data.getPixels()) { - return; - } - - // First update any potentional changes. - updateTextures(); - - // Set the texture. - _target->getTexture()->bind(); - - // Calculate the screen rect where the texture will be drawn. - const GLfloat vertices[4*2] = { - x, y, - x + w, y, - x, y + h, - x + w, y + h - }; - - // Setup coordinates for drawing. - g_context.activePipeline->setDrawCoordinates(vertices, _target->getTexture()->getTexCoords()); - - // Draw the texture to the screen buffer. - GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); -} - Graphics::PixelFormat TextureCLUT8GPU::getFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } @@ -633,7 +579,11 @@ void TextureCLUT8GPU::setPalette(uint start, uint colors, const byte *palData) { _paletteDirty = true; } -void TextureCLUT8GPU::updateTextures() { +const GLTexture &TextureCLUT8GPU::getGLTexture() const { + return *_target->getTexture(); +} + +void TextureCLUT8GPU::updateGLTexture() { const bool needLookUp = Surface::isDirty() || _paletteDirty; // Update CLUT8 texture if necessary. @@ -674,14 +624,10 @@ void TextureCLUT8GPU::lookUpColors() { // Set the palette texture. GL_CALL(glActiveTexture(GL_TEXTURE1)); _paletteTexture.bind(); - - // Set the clut8 texture. GL_CALL(glActiveTexture(GL_TEXTURE0)); - _clut8Texture.bind(); // Do color look up. - g_context.activePipeline->setDrawCoordinates(_clut8Vertices, _clut8Texture.getTexCoords()); - GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); + g_context.activePipeline->drawTexture(_clut8Texture, _clut8Vertices); // Restore old state. g_context.activePipeline->setShader(oldShader); -- cgit v1.2.3 From ed6689d4fcfd30a36cb01392bbd9705732cfac4a Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 28 Feb 2016 17:02:19 +0100 Subject: OPENGL: Do not allow direct access to Context::activePipeline. --- backends/graphics/opengl/texture.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 8b38f85e9f..8746527d5b 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -615,10 +615,10 @@ void TextureCLUT8GPU::updateGLTexture() { void TextureCLUT8GPU::lookUpColors() { // Save old state. - Framebuffer *oldFramebuffer = g_context.activePipeline->setFramebuffer(_target); + Framebuffer *oldFramebuffer = g_context.getActivePipeline()->setFramebuffer(_target); Shader *lookUpShader = ShaderMan.query(ShaderManager::kCLUT8LookUp); - Shader *oldShader = g_context.activePipeline->setShader(lookUpShader); + Shader *oldShader = g_context.getActivePipeline()->setShader(lookUpShader); lookUpShader->setUniformI(_paletteLocation, 1); // Set the palette texture. @@ -627,11 +627,11 @@ void TextureCLUT8GPU::lookUpColors() { GL_CALL(glActiveTexture(GL_TEXTURE0)); // Do color look up. - g_context.activePipeline->drawTexture(_clut8Texture, _clut8Vertices); + g_context.getActivePipeline()->drawTexture(_clut8Texture, _clut8Vertices); // Restore old state. - g_context.activePipeline->setShader(oldShader); - g_context.activePipeline->setFramebuffer(oldFramebuffer); + g_context.getActivePipeline()->setShader(oldShader); + g_context.getActivePipeline()->setFramebuffer(oldFramebuffer); } #endif // !USE_FORCED_GLES -- cgit v1.2.3 From 8a4938f82b05b86c8f0ed010210eb6d1847c04c9 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 28 Feb 2016 18:15:00 +0100 Subject: OPENGL: Move pipeline code to pipelines/. --- backends/graphics/opengl/texture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 8746527d5b..b0e474d415 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -22,7 +22,7 @@ #include "backends/graphics/opengl/texture.h" #include "backends/graphics/opengl/shader.h" -#include "backends/graphics/opengl/pipeline.h" +#include "backends/graphics/opengl/pipelines/pipeline.h" #include "backends/graphics/opengl/framebuffer.h" #include "common/rect.h" -- cgit v1.2.3 From 26f106497a863b84c502d122b5ba749176b2c426 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 28 Feb 2016 23:58:04 +0100 Subject: OPENGL: Implement CLUT8 look up as Pipeline. --- backends/graphics/opengl/texture.cpp | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index b0e474d415..79e3acc7c0 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -23,6 +23,7 @@ #include "backends/graphics/opengl/texture.h" #include "backends/graphics/opengl/shader.h" #include "backends/graphics/opengl/pipelines/pipeline.h" +#include "backends/graphics/opengl/pipelines/clut8.h" #include "backends/graphics/opengl/framebuffer.h" #include "common/rect.h" @@ -489,15 +490,19 @@ void TextureRGB555::updateTexture() { TextureCLUT8GPU::TextureCLUT8GPU() : _clut8Texture(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE), _paletteTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE), - _target(new TextureTarget()), _clut8Vertices(), _paletteLocation(-1), - _clut8Data(), _userPixelData(), _palette(), _paletteDirty(false) { + _target(new TextureTarget()), _clut8Pipeline(new CLUT8LookUpPipeline()), + _clut8Vertices(), _clut8Data(), _userPixelData(), _palette(), + _paletteDirty(false) { // Allocate space for 256 colors. _paletteTexture.setSize(256, 1); - _paletteLocation = ShaderMan.query(ShaderManager::kCLUT8LookUp)->getUniformLocation("palette"); + // Setup pipeline. + _clut8Pipeline->setFramebuffer(_target); + _clut8Pipeline->setPaletteTexture(&_paletteTexture); } TextureCLUT8GPU::~TextureCLUT8GPU() { + delete _clut8Pipeline; delete _target; _clut8Data.free(); } @@ -511,7 +516,6 @@ void TextureCLUT8GPU::destroy() { void TextureCLUT8GPU::recreate() { _clut8Texture.create(); _paletteTexture.create(); - _paletteLocation = ShaderMan.query(ShaderManager::kCLUT8LookUp)->getUniformLocation("palette"); _target->create(); // In case image date exists assure it will be completely refreshed next @@ -614,24 +618,14 @@ void TextureCLUT8GPU::updateGLTexture() { } void TextureCLUT8GPU::lookUpColors() { - // Save old state. - Framebuffer *oldFramebuffer = g_context.getActivePipeline()->setFramebuffer(_target); - - Shader *lookUpShader = ShaderMan.query(ShaderManager::kCLUT8LookUp); - Shader *oldShader = g_context.getActivePipeline()->setShader(lookUpShader); - lookUpShader->setUniformI(_paletteLocation, 1); - - // Set the palette texture. - GL_CALL(glActiveTexture(GL_TEXTURE1)); - _paletteTexture.bind(); - GL_CALL(glActiveTexture(GL_TEXTURE0)); + // Setup pipeline to do color look up. + Pipeline *oldPipeline = g_context.setPipeline(_clut8Pipeline); // Do color look up. g_context.getActivePipeline()->drawTexture(_clut8Texture, _clut8Vertices); // Restore old state. - g_context.getActivePipeline()->setShader(oldShader); - g_context.getActivePipeline()->setFramebuffer(oldFramebuffer); + g_context.setPipeline(oldPipeline); } #endif // !USE_FORCED_GLES -- cgit v1.2.3 From 1e1272a8c4c54d43f076d5a0153db36ee8cbeb42 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 4 Mar 2016 15:32:14 +0100 Subject: OPENGL: Store logical texture dimensions in GLTexture. --- backends/graphics/opengl/texture.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 79e3acc7c0..5252b5a32d 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -46,7 +46,8 @@ static GLuint nextHigher2(GLuint v) { GLTexture::GLTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType) : _glIntFormat(glIntFormat), _glFormat(glFormat), _glType(glType), - _width(0), _height(0), _texCoords(), _glFilter(GL_NEAREST), + _width(0), _height(0), _logicalWidth(0), _logicalHeight(0), + _texCoords(), _glFilter(GL_NEAREST), _glTexture(0) { create(); } @@ -112,6 +113,9 @@ void GLTexture::setSize(uint width, uint height) { _height = height; } + _logicalWidth = width; + _logicalHeight = height; + // If a size is specified, allocate memory for it. if (width != 0 && height != 0) { const GLfloat texWidth = (GLfloat)width / _width; -- cgit v1.2.3 From b7a269947f9b5e40e4baa36d763e5c04551f584c Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 5 Mar 2016 01:20:48 +0100 Subject: OPENGL: Flag texture dirty on allocation. --- backends/graphics/opengl/texture.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 5252b5a32d..8b94549971 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -266,6 +266,12 @@ void Texture::allocate(uint width, uint height) { // Create a sub-buffer for raw access. _userPixelData = _textureData.getSubArea(Common::Rect(width, height)); + + // The whole texture is dirty after we changed the size. This fixes + // multiple texture size changes without any actual update in between. + // Without this we might try to write a too big texture into the GL + // texture. + flagDirty(); } void Texture::updateGLTexture() { @@ -561,6 +567,12 @@ void TextureCLUT8GPU::allocate(uint width, uint height) { _clut8Vertices[6] = width; _clut8Vertices[7] = height; + + // The whole texture is dirty after we changed the size. This fixes + // multiple texture size changes without any actual update in between. + // Without this we might try to write a too big texture into the GL + // texture. + flagDirty(); } Graphics::PixelFormat TextureCLUT8GPU::getFormat() const { -- cgit v1.2.3 From 8ff5329b496c4d599f95eb2703716506bff94ffa Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 3 May 2016 20:39:13 +0200 Subject: OPENGL: Assure color attributes for shader pipeline are always set. --- backends/graphics/opengl/texture.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'backends/graphics/opengl/texture.cpp') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 8b94549971..33598b5488 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -509,6 +509,7 @@ TextureCLUT8GPU::TextureCLUT8GPU() // Setup pipeline. _clut8Pipeline->setFramebuffer(_target); _clut8Pipeline->setPaletteTexture(&_paletteTexture); + _clut8Pipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f); } TextureCLUT8GPU::~TextureCLUT8GPU() { -- cgit v1.2.3