diff --git a/engines/myst3/gfx_opengl_shaders.cpp b/engines/myst3/gfx_opengl_shaders.cpp index 0ae904ca24a..ae3caebaf74 100644 --- a/engines/myst3/gfx_opengl_shaders.cpp +++ b/engines/myst3/gfx_opengl_shaders.cpp @@ -57,6 +57,7 @@ #include "math/rect2d.h" #include "math/quat.h" +#include "graphics/opengles2/extensions.h" #include "graphics/opengles2/shader.h" #include "engines/myst3/gfx.h" @@ -125,7 +126,13 @@ ShaderRenderer::~ShaderRenderer() { } Texture *ShaderRenderer::createTexture(const Graphics::Surface *surface) { - return new OpenGLTexture(surface, true); + OpenGLTexture *texture = new OpenGLTexture(surface, true); + +#if defined(USE_GLES2) + texture->setUnpackSubImageSupport(Graphics::isExtensionSupported("GL_EXT_unpack_subimage")); +#endif + + return texture; } void ShaderRenderer::freeTexture(Texture *texture) { @@ -391,7 +398,18 @@ Graphics::Surface *ShaderRenderer::getScreenshot() { Graphics::Surface *s = new Graphics::Surface(); s->create(screen.width(), screen.height(), Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)); - glReadPixels(screen.left, screen.top, screen.width(), screen.height(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, s->getPixels()); +#if defined(USE_GLES2) + GLenum format = GL_UNSIGNED_BYTE; +#else + GLenum format = GL_UNSIGNED_INT_8_8_8_8_REV; +#endif + + glReadPixels(screen.left, screen.top, screen.width(), screen.height(), GL_RGBA, format, s->getPixels()); + +#if defined(USE_GLES2) && defined(SCUMM_BIG_ENDIAN) + // OpenGL ES does not support the GL_UNSIGNED_INT_8_8_8_8_REV texture format, we need to byteswap the surface + OpenGLTexture::byteswapSurface(s); +#endif flipVertical(s); diff --git a/engines/myst3/gfx_opengl_texture.cpp b/engines/myst3/gfx_opengl_texture.cpp index 4000f735a8c..7a4c8afccdf 100644 --- a/engines/myst3/gfx_opengl_texture.cpp +++ b/engines/myst3/gfx_opengl_texture.cpp @@ -26,6 +26,11 @@ #include "engines/myst3/gfx_opengl_texture.h" +#if !defined(GL_UNPACK_ROW_LENGTH) +// The Android SDK does not declare GL_UNPACK_ROW_LENGTH_EXT +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#endif + namespace Myst3 { // From Bit Twiddling Hacks @@ -40,7 +45,9 @@ static uint32 upperPowerOfTwo(uint32 v) { return v; } -OpenGLTexture::OpenGLTexture(const Graphics::Surface *surface, bool nonPoTSupport) { +OpenGLTexture::OpenGLTexture(const Graphics::Surface *surface, bool nonPoTSupport) : + _unpackSubImageSupport(true) { + width = surface->w; height = surface->h; format = surface->format; @@ -56,7 +63,12 @@ OpenGLTexture::OpenGLTexture(const Graphics::Surface *surface, bool nonPoTSuppor if (format.bytesPerPixel == 4) { internalFormat = GL_RGBA; + +#if defined(USE_GLES2) + sourceFormat = GL_UNSIGNED_BYTE; +#else sourceFormat = GL_UNSIGNED_INT_8_8_8_8_REV; +#endif } else if (format.bytesPerPixel == 2) { internalFormat = GL_RGB; sourceFormat = GL_UNSIGNED_SHORT_5_6_5; @@ -75,6 +87,7 @@ OpenGLTexture::OpenGLTexture(const Graphics::Surface *surface, bool nonPoTSuppor glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); update(surface); + } OpenGLTexture::~OpenGLTexture() { @@ -85,12 +98,50 @@ void OpenGLTexture::update(const Graphics::Surface *surface) { updatePartial(surface, Common::Rect(surface->w, surface->h)); } -void OpenGLTexture::updatePartial(const Graphics::Surface *surface, const Common::Rect &rect) { - const Graphics::Surface subArea = surface->getSubArea(rect); - +void OpenGLTexture::updateTexture(const Graphics::Surface* surface, const Common::Rect& rect) { glBindTexture(GL_TEXTURE_2D, id); - glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->pitch / surface->format.bytesPerPixel); - glTexSubImage2D(GL_TEXTURE_2D, 0, rect.left, rect.top, subArea.w, subArea.h, internalFormat, sourceFormat, subArea.getPixels()); + + if (_unpackSubImageSupport) { + const Graphics::Surface subArea = surface->getSubArea(rect); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->pitch / surface->format.bytesPerPixel); + glTexSubImage2D(GL_TEXTURE_2D, 0, rect.left, rect.top, subArea.w, subArea.h, internalFormat, sourceFormat, subArea.getPixels()); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + } else { + // GL_UNPACK_ROW_LENGTH is not supported, don't bother and do a full texture update + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surface->w, surface->h, internalFormat, sourceFormat, surface->getPixels()); + } +} + +void OpenGLTexture::updatePartial(const Graphics::Surface *surface, const Common::Rect &rect) { +#if defined(USE_GLES2) && defined(SCUMM_BIG_ENDIAN) + // OpenGL ES does not support the GL_UNSIGNED_INT_8_8_8_8_REV texture format + // we need to byteswap before hand + Graphics::Surface swappedSurface; + swappedSurface.copyFrom(*surface); + byteswapSurface(&swappedSurface); + updateTexture(&swappedSurface, rect); + swappedSurface.free(); +#else + updateTexture(surface, rect); +#endif + +} + +void OpenGLTexture::byteswapSurface(Graphics::Surface *surface) { + for (int y = 0; y < surface->h; y++) { + for (int x = 0; x < surface->w; x++) { + if (surface->format.bytesPerPixel == 4) { + uint32 *pixel = (uint32 *) (surface->getBasePtr(x, y)); + *pixel = SWAP_BYTES_32(*pixel); + } else if (surface->format.bytesPerPixel == 2) { + uint16 *pixel = (uint16 *) (surface->getBasePtr(x, y)); + *pixel = SWAP_BYTES_16(*pixel); + } else { + error("Unexpected bytes per pixedl %d", surface->format.bytesPerPixel); + } + } + } } } // End of namespace Myst3 diff --git a/engines/myst3/gfx_opengl_texture.h b/engines/myst3/gfx_opengl_texture.h index 6a527646c4e..382a3639359 100644 --- a/engines/myst3/gfx_opengl_texture.h +++ b/engines/myst3/gfx_opengl_texture.h @@ -39,11 +39,20 @@ public: void update(const Graphics::Surface *surface) override; void updatePartial(const Graphics::Surface *surface, const Common::Rect &rect) override; + void setUnpackSubImageSupport(bool unpackSubImageSupport) { _unpackSubImageSupport = unpackSubImageSupport; } + + static void byteswapSurface(Graphics::Surface *surface); + GLuint id; GLuint internalFormat; GLuint sourceFormat; uint32 internalWidth; uint32 internalHeight; + +private: + void updateTexture(const Graphics::Surface *surface, const Common::Rect &rect); + + bool _unpackSubImageSupport; }; } // End of namespace Myst3