diff options
author | Alejandro Marzini | 2010-07-18 03:25:58 +0000 |
---|---|---|
committer | Alejandro Marzini | 2010-07-18 03:25:58 +0000 |
commit | 492569a7a20d17cfac5fedf1eec1876e53a2767c (patch) | |
tree | 5b684f8101a7e0083ce2133290de4d4425279c3e | |
parent | 0e748c5a9784d19d10c23bb5c72f032a2331567b (diff) | |
download | scummvm-rg350-492569a7a20d17cfac5fedf1eec1876e53a2767c.tar.gz scummvm-rg350-492569a7a20d17cfac5fedf1eec1876e53a2767c.tar.bz2 scummvm-rg350-492569a7a20d17cfac5fedf1eec1876e53a2767c.zip |
Improved cursor drawing.
svn-id: r50976
-rw-r--r-- | backends/graphics/opengl/opengl-graphics.cpp | 236 | ||||
-rw-r--r-- | backends/graphics/opengl/opengl-graphics.h | 80 | ||||
-rw-r--r-- | backends/graphics/openglsdl/openglsdl-graphics.cpp | 2 |
3 files changed, 186 insertions, 132 deletions
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 9a9e30fb69..aecd342c15 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -26,19 +26,20 @@ #ifdef USE_OPENGL #include "backends/graphics/opengl/opengl-graphics.h" +#include "backends/graphics/opengl/glerrorcheck.h" #include "common/mutex.h" #include "common/translation.h" OpenGLGraphicsManager::OpenGLGraphicsManager() : - _gameTexture(0), _overlayTexture(0), _mouseTexture(0), - _overlayVisible(false), - _mouseVisible(false), _mouseNeedsRedraw(false), + _gameTexture(0), _overlayTexture(0), _cursorTexture(0), _screenChangeCount(0), _currentShakePos(0), _newShakePos(0), - _transactionMode(kTransactionNone) - - { + _overlayVisible(false), + _transactionMode(kTransactionNone), + _cursorNeedsRedraw(false), _cursorPaletteDisabled(true), + _cursorVisible(false), _cursorData(0), _cursorKeyColor(0), + _cursorTargetScale(1) { memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); memset(&_videoMode, 0, sizeof(_videoMode)); @@ -48,8 +49,9 @@ OpenGLGraphicsManager::OpenGLGraphicsManager() _videoMode.scaleFactor = 1; _videoMode.fullscreen = false; - _cursorPalette = (uint8 *)calloc(sizeof(uint8), 256); - + _gamePalette = (byte *)calloc(sizeof(byte), 256); + _cursorPalette = (byte *)calloc(sizeof(byte), 256); + // Register the graphics manager as a event observer g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 2, false); } @@ -59,11 +61,17 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() { if (g_system->getEventManager()->getEventDispatcher() != NULL) g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); + free(_gamePalette); free(_cursorPalette); + if (_cursorData != NULL) + free(_cursorData); - delete _gameTexture; - delete _overlayTexture; - delete _mouseTexture; + if (_gameTexture != NULL) + delete _gameTexture; + if (_overlayTexture != NULL) + delete _overlayTexture; + if (_cursorTexture != NULL) + delete _cursorTexture; } // @@ -212,10 +220,6 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { _videoMode.screenWidth == _oldVideoMode.screenWidth && _videoMode.screenHeight == _oldVideoMode.screenHeight) { - // Our new video mode would now be exactly the same as the - // old one. Since we still can not assume SDL_SetVideoMode - // to be working fine, we need to invalidate the old video - // mode, so loadGFXMode would error out properly. _oldVideoMode.setup = false; } } @@ -274,11 +278,28 @@ int16 OpenGLGraphicsManager::getWidth() { } void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) { + assert(colors); + +#ifdef USE_RGB_COLOR + assert(_screenFormat.bytesPerPixel == 1); +#endif + // Save the screen palette + memcpy(_cursorPalette + start * 4, colors, num * 4); + + if (_cursorPaletteDisabled) + _cursorNeedsRedraw = true; } void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) { + assert(colors); + +#ifdef USE_RGB_COLOR + assert(_screenFormat.bytesPerPixel == 1); +#endif + // Copies current palette to buffer + memcpy(colors, _cursorPalette + start * 4, num * 4); } void OpenGLGraphicsManager::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) { @@ -375,22 +396,18 @@ int16 OpenGLGraphicsManager::getOverlayWidth() { // bool OpenGLGraphicsManager::showMouse(bool visible) { - if (_mouseVisible == visible) + if (_cursorVisible == visible) return visible; - bool last = _mouseVisible; - _mouseVisible = visible; - _mouseNeedsRedraw = true; + bool last = _cursorVisible; + _cursorVisible = visible; return last; } void OpenGLGraphicsManager::setMousePos(int x, int y) { - if (x != _mouseCurState.x || y != _mouseCurState.y) { - _mouseNeedsRedraw = true; - _mouseCurState.x = x; - _mouseCurState.y = y; - } + _cursorState.x = x; + _cursorState.y = y; } void OpenGLGraphicsManager::warpMouse(int x, int y) { @@ -398,66 +415,82 @@ void OpenGLGraphicsManager::warpMouse(int x, int y) { } void OpenGLGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { - assert(keycolor < 256); - - // Set cursor info - _mouseCurState.w = w; - _mouseCurState.h = h; - _mouseCurState.hotX = hotspotX; - _mouseCurState.hotY = hotspotY; - - // Allocate a texture big enough for cursor - _mouseTexture->allocBuffer(w, h); - - // Set the key color alpha to 0 - _cursorPalette[keycolor * 4 + 3] = 0; - - // Create a temporary surface - uint8 *surface = new uint8[w * h * 4]; - - // Convert the paletted cursor - const uint8 *src = _cursorPalette; - uint8 *dst = surface; - for (uint i = 0; i < w * h; i++) { - dst[0] = src[buf[i] * 4]; - dst[1] = src[buf[i] * 4 + 1]; - dst[2] = src[buf[i] * 4 + 2]; - dst[3] = src[buf[i] * 4 + 3]; - if (i == (w * 5 + 3)) { - printf("%d,%d,%d,%d - %d,%d,%d,%d - %d\n", dst[0],dst[1],dst[2],dst[3],src[buf[i] * 4],src[buf[i] * 4+1],src[buf[i] * 4+2],src[buf[i] * 4+3],buf[i]); - } - dst += 4; - } - - // Set keycolor alpha back to normal - _cursorPalette[keycolor * 4] = 255; +#ifdef USE_RGB_COLOR + if (!format) + _cursorFormat = Graphics::PixelFormat::createFormatCLUT8(); + else + _cursorFormat = *format; +#else + assert(keycolor <= 255); +#endif - // Update the texture with new cursor - _mouseTexture->updateBuffer(surface, w * 4, 0, 0, w, h); + // Save cursor data + free(_cursorData); + _cursorData = (byte *)malloc(w * h * _cursorFormat.bytesPerPixel); + memcpy(_cursorData, buf, w * h * _cursorFormat.bytesPerPixel); - // Free the temp surface - delete[] surface; + // Set cursor info + _cursorState.w = w; + _cursorState.h = h; + _cursorState.hotX = hotspotX; + _cursorState.hotY = hotspotY; + _cursorKeyColor = keycolor; + _cursorTargetScale = cursorTargetScale; + _cursorNeedsRedraw = true; } void OpenGLGraphicsManager::setCursorPalette(const byte *colors, uint start, uint num) { assert(colors); // Save the cursor palette - uint8 *dst = _cursorPalette + start * 4; - do { - dst[0] = colors[0]; - dst[1] = colors[1]; - dst[2] = colors[2]; - dst[3] = 255; - dst += 4; - colors += 4; - } while(num--); + memcpy(_cursorPalette + start * 4, colors, num * 4); _cursorPaletteDisabled = false; + _cursorNeedsRedraw = true; } void OpenGLGraphicsManager::disableCursorPalette(bool disable) { _cursorPaletteDisabled = disable; + _cursorNeedsRedraw = true; +} + +void OpenGLGraphicsManager::refreshCursor() { + _cursorNeedsRedraw = false; + + if (_cursorFormat == Graphics::PixelFormat::createFormatCLUT8()) { + // Create a temporary RGBA8888 surface + byte *surface = new byte[_cursorState.w * _cursorState.h * 4]; + memset(surface, 0, _cursorState.w * _cursorState.h * 4); + + // Select palette + byte *palette; + if (_cursorPaletteDisabled) + palette = _gamePalette; + else + palette = _cursorPalette; + + // Convert the paletted cursor to RGBA8888 + byte *dst = surface; + for (int i = 0; i < _cursorState.w * _cursorState.h; i++) { + // Check for keycolor + if (_cursorData[i] != _cursorKeyColor) { + dst[0] = palette[_cursorData[i] * 4]; + dst[1] = palette[_cursorData[i] * 4 + 1]; + dst[2] = palette[_cursorData[i] * 4 + 2]; + dst[3] = 255; + } + dst += 4; + } + + // Allocate a texture big enough for cursor + _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h); + + // Update the texture with new cursor + _cursorTexture->updateBuffer(surface, _cursorState.w * 4, 0, 0, _cursorState.w, _cursorState.h); + + // Free the temp surface + delete[] surface; + } } // @@ -504,17 +537,22 @@ void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat, void OpenGLGraphicsManager::internUpdateScreen() { // Clear the screen - glClear( GL_COLOR_BUFFER_BIT ); + CHECK_GL_ERROR( glClear(GL_COLOR_BUFFER_BIT) ); - // Draw the game texture + // Draw the game screen _gameTexture->drawTexture(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight); - // Draw the overlay texture - _overlayTexture->drawTexture(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight); + // Draw the overlay + if (_overlayVisible) + _overlayTexture->drawTexture(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight); - // Draw the mouse texture - _mouseTexture->drawTexture(_mouseCurState.x - _mouseCurState.hotX, - _mouseCurState.y - _mouseCurState.hotY, _mouseCurState.w, _mouseCurState.h); + // Draw the cursor + if (_cursorVisible) { + if (_cursorNeedsRedraw) + refreshCursor(); + _cursorTexture->drawTexture(_cursorState.x - _cursorState.hotX, + _cursorState.y - _cursorState.hotY, _cursorState.w, _cursorState.h); + } } bool OpenGLGraphicsManager::loadGFXMode() { @@ -522,29 +560,29 @@ bool OpenGLGraphicsManager::loadGFXMode() { GLTexture::initGLExtensions(); // Disable 3D properties - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glDisable(GL_FOG); - glDisable(GL_DITHER); - glShadeModel(GL_FLAT); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + CHECK_GL_ERROR( glDisable(GL_CULL_FACE) ); + CHECK_GL_ERROR( glDisable(GL_DEPTH_TEST) ); + CHECK_GL_ERROR( glDisable(GL_LIGHTING) ); + CHECK_GL_ERROR( glDisable(GL_FOG) ); + CHECK_GL_ERROR( glDisable(GL_DITHER) ); + CHECK_GL_ERROR( glShadeModel(GL_FLAT) ); + CHECK_GL_ERROR( glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST) ); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + CHECK_GL_ERROR( glEnable(GL_BLEND) ); + CHECK_GL_ERROR( glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + CHECK_GL_ERROR( glEnableClientState(GL_VERTEX_ARRAY) ); + CHECK_GL_ERROR( glEnableClientState(GL_TEXTURE_COORD_ARRAY) ); - glEnable(GL_TEXTURE_2D); + CHECK_GL_ERROR( glEnable(GL_TEXTURE_2D) ); - glViewport(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight); + CHECK_GL_ERROR( glViewport(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight) ); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, _videoMode.hardwareWidth, _videoMode.hardwareHeight, 0, -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + CHECK_GL_ERROR( glMatrixMode(GL_PROJECTION) ); + CHECK_GL_ERROR( glLoadIdentity() ); + CHECK_GL_ERROR( glOrtho(0, _videoMode.hardwareWidth, _videoMode.hardwareHeight, 0, -1, 1) ); + CHECK_GL_ERROR( glMatrixMode(GL_MODELVIEW) ); + CHECK_GL_ERROR( glLoadIdentity() ); if (!_gameTexture) { byte bpp; @@ -562,14 +600,14 @@ bool OpenGLGraphicsManager::loadGFXMode() { else _overlayTexture->refresh(); - if (!_mouseTexture) - _mouseTexture = new GLTexture(4, GL_RGBA, GL_UNSIGNED_BYTE); + if (!_cursorTexture) + _cursorTexture = new GLTexture(4, GL_RGBA, GL_UNSIGNED_BYTE); else - _mouseTexture->refresh(); + _cursorTexture->refresh(); _gameTexture->allocBuffer(_videoMode.screenWidth, _videoMode.screenHeight); _overlayTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight); - _mouseTexture->allocBuffer(16, 16); + _cursorTexture->allocBuffer(16, 16); internUpdateScreen(); diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index d02fcd7fe4..3da501f933 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -100,28 +100,9 @@ public: bool notifyEvent(const Common::Event &event); protected: - GLTexture* _gameTexture; - GLTexture* _overlayTexture; - GLTexture* _mouseTexture; - - virtual void getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &glFormat, GLenum &type); - - virtual void internUpdateScreen(); - virtual bool loadGFXMode(); - virtual void unloadGFXMode(); - virtual bool hotswapGFXMode(); - - Graphics::Surface _lockedScreen; - int _screenChangeCount; - -#ifdef USE_RGB_COLOR - Graphics::PixelFormat _screenFormat; - Graphics::PixelFormat _cursorFormat; -#endif - - bool _overlayVisible; - Graphics::PixelFormat _overlayFormat; - + // + // GFX and video + // enum { kTransactionNone = 0, kTransactionActive = 1, @@ -158,7 +139,39 @@ protected: }; VideoState _videoMode, _oldVideoMode; + virtual void getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &glFormat, GLenum &type); + + virtual void internUpdateScreen(); + virtual bool loadGFXMode(); + virtual void unloadGFXMode(); + virtual bool hotswapGFXMode(); + + // + // Game screen + // + GLTexture* _gameTexture; + Graphics::Surface _lockedScreen; + int _screenChangeCount; + +#ifdef USE_RGB_COLOR + Graphics::PixelFormat _screenFormat; +#endif + byte *_gamePalette; + + // Shake mode + int _currentShakePos; + int _newShakePos; + + // + // Overlay + // + GLTexture* _overlayTexture; + bool _overlayVisible; + Graphics::PixelFormat _overlayFormat; + // + // Mouse + // struct MousePos { // The mouse position, using either virtual (game) or real // (overlay) coordinates. @@ -184,19 +197,22 @@ protected: { } }; - MousePos _mouseCurState; - bool _mouseVisible; - bool _mouseNeedsRedraw; - - uint8 *_cursorPalette; + GLTexture* _cursorTexture; +#ifdef USE_RGB_COLOR + Graphics::PixelFormat _cursorFormat; +#endif + byte *_cursorPalette; bool _cursorPaletteDisabled; - + MousePos _cursorState; + bool _cursorVisible; + byte *_cursorData; + uint32 _cursorKeyColor; + int _cursorTargetScale; + bool _cursorNeedsRedraw; + + virtual void refreshCursor(); virtual void adjustMouseEvent(const Common::Event &event); virtual void setMousePos(int x, int y); - - // Shake mode - int _currentShakePos; - int _newShakePos; }; #endif diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index 7abb4feb44..98e67d2e78 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -101,7 +101,7 @@ Common::List<Graphics::PixelFormat> OpenGLSdlGraphicsManager::getSupportedFormat #endif void OpenGLSdlGraphicsManager::warpMouse(int x, int y) { - if (_mouseCurState.x != x || _mouseCurState.y != y) { + if (_cursorState.x != x || _cursorState.y != y) { int y1 = y; /*if (_videoMode.aspectRatioCorrection && !_overlayVisible) |