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/opengl-graphics.cpp | 9 ++++ backends/graphics/opengl/texture.cpp | 60 ++++++++++++++++++++++ backends/graphics/opengl/texture.h | 21 ++++++++ backends/graphics/openglsdl/openglsdl-graphics.cpp | 7 ++- 4 files changed, 95 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 78ae27d8a6..8db5f6a934 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -985,6 +985,15 @@ Texture *OpenGLGraphicsManager::createTexture(const Graphics::PixelFormat &forma } else { return new TextureCLUT8(glIntFormat, glFormat, glType, virtFormat); } +#if !USE_FORCED_GL + } else if (isGLESContext() && format == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { + // OpenGL ES does not support a texture format usable for RGB555. + // Since SCUMM uses this pixel format for some games (and there is no + // hope for this to change anytime soon) we use pixel format + // conversion to a supported texture format. However, this is a one + // time exception. + return new TextureRGB555(); +#endif // !USE_FORCED_GL } else { const bool supported = getGLPixelFormat(format, glIntFormat, glFormat, glType); if (!supported) { 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 diff --git a/backends/graphics/opengl/texture.h b/backends/graphics/opengl/texture.h index ad70833544..4c2126741c 100644 --- a/backends/graphics/opengl/texture.h +++ b/backends/graphics/opengl/texture.h @@ -170,6 +170,27 @@ private: byte *_palette; }; +#if !USE_FORCED_GL +class TextureRGB555 : public Texture { +public: + TextureRGB555(); + virtual ~TextureRGB555(); + + virtual void allocate(uint width, uint height); + + virtual Graphics::PixelFormat getFormat() const; + + virtual Graphics::Surface *getSurface() { return &_rgb555Data; } + virtual const Graphics::Surface *getSurface() const { return &_rgb555Data; } + +protected: + virtual void updateTexture(); + +private: + Graphics::Surface _rgb555Data; +}; +#endif // !USE_FORCED_GL + } // End of namespace OpenGL #endif diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index a945138578..583d54b30b 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -221,13 +221,16 @@ Common::List OpenGLSdlGraphicsManager::getSupportedFormat // ABGR8888 formats.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)); #endif - // RGB555, this is used by SCUMM HE 16 bit games. - formats.push_back(Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)); #if !USE_FORCED_GL } #endif #endif + // RGB555, this is used by SCUMM HE 16 bit games. + // This is not natively supported by OpenGL ES implementations, we convert + // the pixel format internally. + formats.push_back(Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)); + formats.push_back(Graphics::PixelFormat::createFormatCLUT8()); return formats; -- cgit v1.2.3