aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/graphics/opengl/gltexture.cpp57
-rw-r--r--backends/graphics/opengl/gltexture.h37
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp347
-rw-r--r--backends/graphics/opengl/opengl-graphics.h38
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.cpp29
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.h3
6 files changed, 377 insertions, 134 deletions
diff --git a/backends/graphics/opengl/gltexture.cpp b/backends/graphics/opengl/gltexture.cpp
index 98291edfac..188386d0ab 100644
--- a/backends/graphics/opengl/gltexture.cpp
+++ b/backends/graphics/opengl/gltexture.cpp
@@ -56,18 +56,22 @@ static GLuint nextHigher2(GLuint v) {
void GLTexture::initGLExtensions() {
static bool inited = false;
+ // Return if extensions already checked
if (inited)
return;
+ // Get a string with all extensions
const char* ext_string =
reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
CHECK_GL_ERROR();
Common::StringTokenizer tokenizer(ext_string, " ");
+ // Iterate all string tokens
while (!tokenizer.empty()) {
Common::String token = tokenizer.nextToken();
if (token == "GL_ARB_texture_non_power_of_two")
npot_supported = true;
}
+
inited = true;
}
@@ -83,31 +87,21 @@ GLTexture::GLTexture(byte bpp, GLenum format, GLenum type)
_refresh(false),
_filter(GL_NEAREST) {
- // Generates the texture ID for GL
+ // Generate the texture ID
glGenTextures(1, &_textureName); CHECK_GL_ERROR();
-
- // This all gets reset later in allocBuffer:
- _surface.w = 0;
- _surface.h = 0;
- _surface.pitch = 0;
- _surface.pixels = NULL;
- _surface.bytesPerPixel = 0;
}
GLTexture::~GLTexture() {
+ // Delete the texture
glDeleteTextures(1, &_textureName); CHECK_GL_ERROR();
}
void GLTexture::refresh() {
- // Generates the texture ID for GL
+ // Generate the texture ID
glGenTextures(1, &_textureName); CHECK_GL_ERROR();
_refresh = true;
}
-void GLTexture::refreshBuffer() {
- updateBuffer(_surface.pixels, _surface.pitch, 0, 0, _surface.w, _surface.h);
-}
-
void GLTexture::allocBuffer(GLuint w, GLuint h) {
_realWidth = w;
_realHeight = h;
@@ -124,62 +118,47 @@ void GLTexture::allocBuffer(GLuint w, GLuint h) {
_textureHeight = nextHigher2(h);
}
- // Allocate room for the texture now, but pixel data gets uploaded
- // later (perhaps with multiple TexSubImage2D operations).
+ // Select this OpenGL texture
glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR();
+
+ // Set the texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _filter); CHECK_GL_ERROR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _filter); CHECK_GL_ERROR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); CHECK_GL_ERROR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); CHECK_GL_ERROR();
+
+ // Allocate room for the texture
glTexImage2D(GL_TEXTURE_2D, 0, _glFormat,
_textureWidth, _textureHeight, 0, _glFormat, _glType, NULL); CHECK_GL_ERROR();
- if (_surface.w != _textureWidth || _surface.h != _textureHeight)
- _surface.create(_textureWidth, _textureHeight, _bytesPerPixel);
- else if (_refresh)
- refreshBuffer();
-
_refresh = false;
}
void GLTexture::updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, GLuint w, GLuint h) {
+ // Select this OpenGL texture
glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR();
+ // Check if the buffer has its data contiguously
if (static_cast<int>(w) * _bytesPerPixel == pitch) {
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
_glFormat, _glType, buf); CHECK_GL_ERROR();
- if (buf != _surface.pixels)
- memcpy(_surface.getBasePtr(x, y), buf, h * pitch);
} else {
+ // Update the texture row by row
const byte *src = static_cast<const byte *>(buf);
do {
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y,
w, 1, _glFormat, _glType, src); CHECK_GL_ERROR();
- if (buf != _surface.pixels)
- memcpy(_surface.getBasePtr(x, y), src, w * _bytesPerPixel);
++y;
src += pitch;
} while (--h);
}
}
-void GLTexture::fillBuffer(uint32 x) {
- if (_bytesPerPixel == 1)
- memset(_surface.pixels, x, _surface.w * _surface.h);
- else {
- for (int i = 0; i < _surface.w * _surface.h; i++) {
- memcpy(_surface.pixels, &x, _bytesPerPixel);
- }
- }
-
- glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR();
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _surface.w, _surface.h,
- _glFormat, _glType, _surface.pixels); CHECK_GL_ERROR();
-}
-
void GLTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
+ // Select this OpenGL texture
glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR();
+ // Calculate the texture rect that will be drawn
const GLfloat texWidth = (GLfloat)_realWidth / _textureWidth;//xdiv(_surface.w, _textureWidth);
const GLfloat texHeight = (GLfloat)_realHeight / _textureHeight;//xdiv(_surface.h, _textureHeight);
const GLfloat texcoords[] = {
@@ -190,6 +169,7 @@ void GLTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
};
glTexCoordPointer(2, GL_FLOAT, 0, texcoords); CHECK_GL_ERROR();
+ // Calculate the screen rect where the texture will be drawn
const GLshort vertices[] = {
x, y,
x + w, y,
@@ -198,6 +178,7 @@ void GLTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
};
glVertexPointer(2, GL_SHORT, 0, vertices); CHECK_GL_ERROR();
+ // Draw the texture to the screen buffer
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); CHECK_GL_ERROR();
}
diff --git a/backends/graphics/opengl/gltexture.h b/backends/graphics/opengl/gltexture.h
index abdb7eceaa..73771fda91 100644
--- a/backends/graphics/opengl/gltexture.h
+++ b/backends/graphics/opengl/gltexture.h
@@ -53,28 +53,50 @@
*/
class GLTexture {
public:
+ /**
+ * Initialize OpenGL Extensions
+ */
static void initGLExtensions();
GLTexture(byte bpp, GLenum format, GLenum type);
virtual ~GLTexture();
+ /**
+ * Refresh the texture after a context change. The
+ * process will be completed on next allocBuffer call.
+ */
virtual void refresh();
- virtual void refreshBuffer();
+ /**
+ * Allocates memory needed for the given size.
+ */
virtual void allocBuffer(GLuint width, GLuint height);
- virtual void fillBuffer(uint32 x);
+
+ /**
+ * Updates the texture pixels.
+ */
virtual void updateBuffer(const void *buf, int pitch, GLuint x, GLuint y,
GLuint w, GLuint h);
- virtual void drawTexture() { drawTexture(0, 0, _realWidth, _realHeight); }
+ /**
+ * Draws the texture to the screen buffer.
+ */
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
- Graphics::Surface *getSurface() { return &_surface; }
-
+ /**
+ * Get the texture width.
+ */
GLuint getWidth() const { return _realWidth; }
+
+ /**
+ * Get the texture height.
+ */
GLuint getHeight() const { return _realHeight; }
- GLuint getTextureName() const { return _textureName; }
+ /**
+ * Set the texture filter.
+ * GL_NEAREST or GL_LINEAR should be passed.
+ */
void setFilter(GLint filter) { _filter = filter; }
protected:
@@ -82,12 +104,11 @@ protected:
const GLenum _glFormat;
const GLenum _glType;
- Graphics::Surface _surface;
GLuint _realWidth;
GLuint _realHeight;
GLuint _textureName;
GLuint _textureWidth;
GLuint _textureHeight;
- bool _refresh;
GLint _filter;
+ bool _refresh;
};
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index 5bb496d1ba..6ba4fed474 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -33,20 +33,20 @@
OpenGLGraphicsManager::OpenGLGraphicsManager()
:
_gameTexture(0), _overlayTexture(0), _cursorTexture(0),
- _screenChangeCount(0),
+ _screenChangeCount(0), _screenNeedsRedraw(false),
_currentShakePos(0), _newShakePos(0),
- _overlayVisible(false),
+ _overlayVisible(false), _overlayNeedsRedraw(false),
_transactionMode(kTransactionNone),
_cursorNeedsRedraw(false), _cursorPaletteDisabled(true),
- _cursorVisible(false), _cursorData(0), _cursorKeyColor(0),
+ _cursorVisible(false), _cursorKeyColor(0),
_cursorTargetScale(1) {
memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
memset(&_videoMode, 0, sizeof(_videoMode));
memset(&_transactionDetails, 0, sizeof(_transactionDetails));
- _videoMode.mode = OpenGL::GFX_NORMAL;
- _videoMode.scaleFactor = 1;
+ _videoMode.mode = OpenGL::GFX_DOUBLESIZE;
+ _videoMode.scaleFactor = 2;
_videoMode.fullscreen = false;
_videoMode.antialiasing = false;
@@ -64,8 +64,6 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() {
free(_gamePalette);
free(_cursorPalette);
- if (_cursorData != NULL)
- free(_cursorData);
if (_gameTexture != NULL)
delete _gameTexture;
@@ -80,11 +78,19 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() {
//
bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) {
- return (f == OSystem::kFeatureCursorHasPalette);
+ return
+ (f == OSystem::kFeatureAspectRatioCorrection) ||
+ (f == OSystem::kFeatureCursorHasPalette);
}
void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
-
+ switch (f) {
+ case OSystem::kFeatureAspectRatioCorrection:
+ setAspectRatioCorrection(enable ? -1 : 0);
+ break;
+ default:
+ break;
+ }
}
bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) {
@@ -225,10 +231,10 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
errors |= OSystem::kTransactionFullscreenFailed;
_videoMode.fullscreen = _oldVideoMode.fullscreen;
- /*} else if (_videoMode.aspectRatioCorrection != _oldVideoMode.aspectRatioCorrection) {
+ } else if (_videoMode.aspectRatioCorrection != _oldVideoMode.aspectRatioCorrection) {
errors |= OSystem::kTransactionAspectRatioFailed;
- _videoMode.aspectRatioCorrection = _oldVideoMode.aspectRatioCorrection;*/
+ _videoMode.aspectRatioCorrection = _oldVideoMode.aspectRatioCorrection;
} else if (_videoMode.mode != _oldVideoMode.mode) {
errors |= OSystem::kTransactionModeSwitchFailed;
@@ -251,7 +257,7 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
}
if (_videoMode.fullscreen == _oldVideoMode.fullscreen &&
- //_videoMode.aspectRatioCorrection == _oldVideoMode.aspectRatioCorrection &&
+ _videoMode.aspectRatioCorrection == _oldVideoMode.aspectRatioCorrection &&
_videoMode.mode == _oldVideoMode.mode &&
_videoMode.screenWidth == _oldVideoMode.screenWidth &&
_videoMode.screenHeight == _oldVideoMode.screenHeight) {
@@ -310,6 +316,8 @@ void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num)
// Save the screen palette
memcpy(_gamePalette + start * 4, colors, num * 4);
+ _screenNeedsRedraw = true;
+
if (_cursorPaletteDisabled)
_cursorNeedsRedraw = true;
}
@@ -326,45 +334,65 @@ void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) {
}
void OpenGLGraphicsManager::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
- if (_screenFormat == Graphics::PixelFormat::createFormatCLUT8()) {
- // Create a temporary RGBA888 surface
- byte *surface = new byte[w * h * 3];
-
- // Convert the paletted buffer to RGBA888
- const byte *src = buf;
- byte *dst = surface;
- for (int i = 0; i < h; i++) {
- for (int j = 0; j < w; j++) {
- dst[0] = _gamePalette[src[j] * 4];
- dst[1] = _gamePalette[src[j] * 4 + 1];
- dst[2] = _gamePalette[src[j] * 4 + 2];
- dst += 3;
- }
- src += pitch;
- }
-
- // Update the texture
- _gameTexture->updateBuffer(surface, w * 3, x, y, w, h);
+ assert(x >= 0 && x < _screenData.w);
+ assert(y >= 0 && y < _screenData.h);
+ assert(h > 0 && y + h <= _screenData.h);
+ assert(w > 0 && x + w <= _screenData.w);
+
+ // Copy buffer data to game screen internal buffer
+ const byte *src = buf;
+ byte *dst = (byte *)_screenData.pixels + y * _screenData.pitch;
+ for (int i = 0; i < h; i++) {
+ memcpy(dst + x * _screenData.bytesPerPixel, src, w * _screenData.bytesPerPixel);
+ src += pitch;
+ dst += _screenData.pitch;
+ }
- // Free the temp surface
- delete[] surface;
- } else
- _gameTexture->updateBuffer(buf, pitch, x, y, w, h);
+ if (!_screenNeedsRedraw) {
+ const Common::Rect dirtyRect(x, y, x + w, y + h);
+ _screenDirtyRect.extend(dirtyRect);
+ }
}
Graphics::Surface *OpenGLGraphicsManager::lockScreen() {
- return _gameTexture->getSurface();
+ return &_screenData;
}
void OpenGLGraphicsManager::unlockScreen() {
- _gameTexture->refreshBuffer();
+ _screenNeedsRedraw = true;
}
void OpenGLGraphicsManager::fillScreen(uint32 col) {
if (_gameTexture == NULL)
return;
- _gameTexture->fillBuffer(col);
+ if (_screenFormat.bytesPerPixel == 1) {
+ memset(_screenData.pixels, col, _screenData.h * _screenData.pitch);
+ } else if (_screenFormat.bytesPerPixel == 2) {
+ uint16 *pixels = (uint16 *)_screenData.pixels;
+ uint16 col16 = (uint16)col;
+ for (int i = 0; i < _screenData.w * _screenData.h; i++) {
+ pixels[i] = col16;
+ }
+ } else if (_screenFormat.bytesPerPixel == 3) {
+ uint8 *pixels = (uint8 *)_screenData.pixels;
+ byte r = (col >> 16) & 0xFF;
+ byte g = (col >> 8) & 0xFF;
+ byte b = col & 0xFF;
+ for (int i = 0; i < _screenData.w * _screenData.h; i++) {
+ pixels[0] = r;
+ pixels[1] = g;
+ pixels[2] = b;
+ pixels += 3;
+ }
+ } else if (_screenFormat.bytesPerPixel == 4) {
+ uint32 *pixels = (uint32 *)_screenData.pixels;
+ for (int i = 0; i < _screenData.w * _screenData.h; i++) {
+ pixels[i] = col;
+ }
+ }
+
+ _screenNeedsRedraw = true;
}
void OpenGLGraphicsManager::updateScreen() {
@@ -392,13 +420,23 @@ void OpenGLGraphicsManager::clearFocusRectangle() {
void OpenGLGraphicsManager::showOverlay() {
assert (_transactionMode == kTransactionNone);
+ if (_overlayVisible)
+ return;
+
_overlayVisible = true;
+
+ clearOverlay();
}
void OpenGLGraphicsManager::hideOverlay() {
assert (_transactionMode == kTransactionNone);
+ if (!_overlayVisible)
+ return;
+
_overlayVisible = false;
+
+ clearOverlay();
}
Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const {
@@ -406,21 +444,18 @@ Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const {
}
void OpenGLGraphicsManager::clearOverlay() {
- _overlayTexture->fillBuffer(0);
+ memset(_overlayData.pixels, 0, _overlayData.h * _overlayData.pitch);
+ _overlayNeedsRedraw = true;
}
void OpenGLGraphicsManager::grabOverlay(OverlayColor *buf, int pitch) {
- const Graphics::Surface *surface = _overlayTexture->getSurface();
- assert(surface->bytesPerPixel == sizeof(buf[0]));
- uint w = _overlayTexture->getWidth();
- uint h = _overlayTexture->getHeight();
- const byte *src = (byte *)surface->pixels;
- do {
- //memset(buf, 0, w * sizeof(buf[0]));
- memcpy(buf, src, w * sizeof(buf[0]));
+ assert(_overlayData.bytesPerPixel == sizeof(buf[0]));
+ const byte *src = (byte *)_overlayData.pixels;
+ for (int i = 0; i < _overlayData.h; i++) {
+ memcpy(buf, src, _overlayData.pitch);
buf += pitch;
- src += surface->pitch;
- } while (--h);
+ src += _overlayData.pitch;
+ }
}
void OpenGLGraphicsManager::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
@@ -429,7 +464,40 @@ void OpenGLGraphicsManager::copyRectToOverlay(const OverlayColor *buf, int pitch
if (_overlayTexture == NULL)
return;
- _overlayTexture->updateBuffer(buf, pitch * sizeof(buf[0]), x, y, w, h);
+ // Clip the coordinates
+ if (x < 0) {
+ w += x;
+ buf -= x;
+ x = 0;
+ }
+
+ if (y < 0) {
+ h += y; buf -= y * pitch;
+ y = 0;
+ }
+
+ if (w > _overlayData.w - x)
+ w = _overlayData.w - x;
+
+ if (h > _overlayData.h - y)
+ h = _overlayData.h - y;
+
+ if (w <= 0 || h <= 0)
+ return;
+
+ // Copy buffer data to internal overlay surface
+ const byte *src = (byte *)buf;
+ byte *dst = (byte *)_overlayData.pixels + y * _overlayData.pitch;
+ for (int i = 0; i < h; i++) {
+ memcpy(dst + x * _overlayData.bytesPerPixel, src, w * _overlayData.bytesPerPixel);
+ src += pitch * sizeof(buf[0]);
+ dst += _overlayData.pitch;
+ }
+
+ if (!_overlayNeedsRedraw) {
+ const Common::Rect dirtyRect(x, y, x + w, y + h);
+ _overlayDirtyRect.extend(dirtyRect);
+ }
}
int16 OpenGLGraphicsManager::getOverlayHeight() {
@@ -474,9 +542,8 @@ void OpenGLGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int
#endif
// Save cursor data
- free(_cursorData);
- _cursorData = (byte *)malloc(w * h * _cursorFormat.bytesPerPixel);
- memcpy(_cursorData, buf, w * h * _cursorFormat.bytesPerPixel);
+ _cursorData.create(w, h, _cursorFormat.bytesPerPixel);
+ memcpy(_cursorData.pixels, buf, h * _cursorData.pitch);
// Set cursor info
_cursorState.w = w;
@@ -503,10 +570,106 @@ void OpenGLGraphicsManager::disableCursorPalette(bool disable) {
_cursorNeedsRedraw = true;
}
+//
+// Misc
+//
+
+void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) {
+
+}
+
+//
+// Intern
+//
+
+void OpenGLGraphicsManager::refreshGameScreen() {
+ if (_screenNeedsRedraw)
+ _screenDirtyRect = Common::Rect(0, 0, _screenData.w, _screenData.h);
+
+ int x = _screenDirtyRect.left;
+ int y = _screenDirtyRect.top;
+ int w = _screenDirtyRect.width();
+ int h = _screenDirtyRect.height();
+
+ if (_screenData.bytesPerPixel == 1) {
+ // Create a temporary RGB888 surface
+ byte *surface = new byte[w * h * 3];
+
+ // Convert the paletted buffer to RGB888
+ const byte *src = (byte *)_screenData.pixels + y * _screenData.pitch;
+ src += x * _screenData.bytesPerPixel;
+ byte *dst = surface;
+ for (int i = 0; i < h; i++) {
+ for (int j = 0; j < w; j++) {
+ dst[0] = _gamePalette[src[j] * 4];
+ dst[1] = _gamePalette[src[j] * 4 + 1];
+ dst[2] = _gamePalette[src[j] * 4 + 2];
+ dst += 3;
+ }
+ src += _screenData.pitch;
+ }
+
+ // Update the texture
+ _gameTexture->updateBuffer(surface, w * 3, x, y, w, h);
+
+ // Free the temp surface
+ delete[] surface;
+ } else {
+ // Update the texture
+ _gameTexture->updateBuffer((byte *)_screenData.pixels + y * _screenData.pitch +
+ x * _screenData.bytesPerPixel, _screenData.pitch, x, y, w, h);
+ }
+
+ _screenNeedsRedraw = false;
+ _screenDirtyRect = Common::Rect();
+}
+
+void OpenGLGraphicsManager::refreshOverlay() {
+ if (_overlayNeedsRedraw)
+ _overlayDirtyRect = Common::Rect(0, 0, _overlayData.w, _overlayData.h);
+
+ int x = _overlayDirtyRect.left;
+ int y = _overlayDirtyRect.top;
+ int w = _overlayDirtyRect.width();
+ int h = _overlayDirtyRect.height();
+
+ if (_overlayData.bytesPerPixel == 1) {
+ // Create a temporary RGB888 surface
+ byte *surface = new byte[w * h * 3];
+
+ // Convert the paletted buffer to RGB888
+ const byte *src = (byte *)_overlayData.pixels + y * _overlayData.pitch;
+ src += x * _overlayData.bytesPerPixel;
+ byte *dst = surface;
+ for (int i = 0; i < h; i++) {
+ for (int j = 0; j < w; j++) {
+ dst[0] = _gamePalette[src[j] * 4];
+ dst[1] = _gamePalette[src[j] * 4 + 1];
+ dst[2] = _gamePalette[src[j] * 4 + 2];
+ dst += 3;
+ }
+ src += _screenData.pitch;
+ }
+
+ // Update the texture
+ _overlayTexture->updateBuffer(surface, w * 3, x, y, w, h);
+
+ // Free the temp surface
+ delete[] surface;
+ } else {
+ // Update the texture
+ _overlayTexture->updateBuffer((byte *)_overlayData.pixels + y * _overlayData.pitch +
+ x * _overlayData.bytesPerPixel, _overlayData.pitch, x, y, w, h);
+ }
+
+ _overlayNeedsRedraw = false;
+ _overlayDirtyRect = Common::Rect();
+}
+
void OpenGLGraphicsManager::refreshCursor() {
_cursorNeedsRedraw = false;
- if (_cursorFormat == Graphics::PixelFormat::createFormatCLUT8()) {
+ if (_cursorFormat.bytesPerPixel == 1) {
// Create a temporary RGBA8888 surface
byte *surface = new byte[_cursorState.w * _cursorState.h * 4];
memset(surface, 0, _cursorState.w * _cursorState.h * 4);
@@ -519,13 +682,14 @@ void OpenGLGraphicsManager::refreshCursor() {
palette = _cursorPalette;
// Convert the paletted cursor to RGBA8888
+ const byte *src = (byte *)_cursorData.pixels;
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];
+ if (src[i] != _cursorKeyColor) {
+ dst[0] = palette[src[i] * 4];
+ dst[1] = palette[src[i] * 4 + 1];
+ dst[2] = palette[src[i] * 4 + 2];
dst[3] = 255;
}
dst += 4;
@@ -542,18 +706,6 @@ void OpenGLGraphicsManager::refreshCursor() {
}
}
-//
-// Misc
-//
-
-void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) {
-
-}
-
-//
-// Intern
-//
-
void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &glFormat, GLenum &gltype) {
if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888
bpp = 4;
@@ -575,13 +727,14 @@ void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat,
bpp = 2;
glFormat = GL_RGBA;
gltype = GL_UNSIGNED_SHORT_4_4_4_4;
- } else if (pixelFormat == Graphics::PixelFormat::createFormatCLUT8()) { // CLUT8
- // If uses a palette, create as RGBA888, then convert
+ } else if (pixelFormat.bytesPerPixel == 1) { // CLUT8
+ // If uses a palette, create texture as RGB888. The pixel data will be converted
+ // later.
bpp = 3;
glFormat = GL_RGB;
gltype = GL_UNSIGNED_BYTE;
} else {
- error("Not supported format");
+ error("Pixel format not supported");
}
}
@@ -590,16 +743,29 @@ void OpenGLGraphicsManager::internUpdateScreen() {
glClear(GL_COLOR_BUFFER_BIT); CHECK_GL_ERROR();
// Draw the game screen
+ if (_screenNeedsRedraw || !_screenDirtyRect.isEmpty())
+ // Refresh texture if dirty
+ refreshGameScreen();
+
_gameTexture->drawTexture(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight);
// Draw the overlay
- if (_overlayVisible)
+ if (_overlayVisible) {
+
+ // Refresh texture if dirty
+ if (_overlayNeedsRedraw || !_overlayDirtyRect.isEmpty())
+ refreshOverlay();
+
_overlayTexture->drawTexture(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight);
+ }
// Draw the cursor
if (_cursorVisible) {
+
+ // Refresh texture if dirty
if (_cursorNeedsRedraw)
refreshCursor();
+
_cursorTexture->drawTexture(_cursorState.x - _cursorState.hotX,
_cursorState.y - _cursorState.hotY, _cursorState.w, _cursorState.h);
}
@@ -640,6 +806,11 @@ void OpenGLGraphicsManager::initGL() {
}
void OpenGLGraphicsManager::loadTextures() {
+#ifdef USE_RGB_COLOR
+ if (_transactionDetails.formatChanged && _gameTexture)
+ delete _gameTexture;
+#endif
+
if (!_gameTexture) {
byte bpp;
GLenum format;
@@ -679,6 +850,21 @@ void OpenGLGraphicsManager::loadTextures() {
_gameTexture->allocBuffer(_videoMode.screenWidth, _videoMode.screenHeight);
_overlayTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight);
_cursorTexture->allocBuffer(_cursorState.w, _cursorState.h);
+
+ if (_transactionDetails.formatChanged ||
+ _oldVideoMode.screenWidth != _videoMode.screenWidth ||
+ _oldVideoMode.screenHeight != _videoMode.screenHeight)
+ _screenData.create(_videoMode.screenWidth, _videoMode.screenHeight,
+ _screenFormat.bytesPerPixel);
+
+ if (_oldVideoMode.overlayWidth != _videoMode.overlayWidth ||
+ _oldVideoMode.overlayHeight != _videoMode.overlayHeight)
+ _overlayData.create(_videoMode.overlayWidth, _videoMode.overlayHeight,
+ _overlayFormat.bytesPerPixel);
+
+ _screenNeedsRedraw = true;
+ _overlayNeedsRedraw = true;
+ _cursorNeedsRedraw = true;
}
bool OpenGLGraphicsManager::loadGFXMode() {
@@ -705,6 +891,19 @@ void OpenGLGraphicsManager::setScale(int newScale) {
_transactionDetails.sizeChanged = true;
}
+void OpenGLGraphicsManager::setAspectRatioCorrection(int ratio) {
+ if (_oldVideoMode.setup && _oldVideoMode.aspectRatioCorrection == ratio)
+ return;
+
+ if (_transactionMode == kTransactionActive) {
+ if (ratio == -1)
+ _videoMode.aspectRatioCorrection = (_videoMode.aspectRatioCorrection + 1) % 4;
+ else
+ _videoMode.aspectRatioCorrection = ratio;
+ _transactionDetails.needHotswap = true;
+ }
+}
+
void OpenGLGraphicsManager::adjustMouseEvent(const Common::Event &event) {
if (!event.synthetic) {
Common::Event newEvent(event);
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index e366216a8c..a372cb9d0d 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -126,12 +126,18 @@ protected:
TransactionDetails _transactionDetails;
int _transactionMode;
+ enum {
+ kAspectRatioNone,
+ kAspectRatioConserve,
+ kAspectRatio4_3,
+ kAspectRatio16_10
+ };
+
struct VideoState {
bool setup;
bool fullscreen;
- //bool aspectRatioCorrection;
- //AspectRatio desiredAspectRatio;
+ int aspectRatioCorrection;
int mode;
int scaleFactor;
@@ -153,19 +159,24 @@ protected:
virtual void unloadGFXMode();
virtual void setScale(int newScale);
+ virtual void setAspectRatioCorrection(int mode);
//
// Game screen
//
GLTexture* _gameTexture;
- Graphics::Surface _lockedScreen;
+ Graphics::Surface _screenData;
int _screenChangeCount;
+ bool _screenNeedsRedraw;
+ Common::Rect _screenDirtyRect;
#ifdef USE_RGB_COLOR
Graphics::PixelFormat _screenFormat;
#endif
byte *_gamePalette;
+ virtual void refreshGameScreen();
+
// Shake mode
int _currentShakePos;
int _newShakePos;
@@ -174,8 +185,13 @@ protected:
// Overlay
//
GLTexture* _overlayTexture;
- bool _overlayVisible;
+ Graphics::Surface _overlayData;
Graphics::PixelFormat _overlayFormat;
+ bool _overlayVisible;
+ bool _overlayNeedsRedraw;
+ Common::Rect _overlayDirtyRect;
+
+ virtual void refreshOverlay();
//
// Mouse
@@ -191,21 +207,22 @@ protected:
// The size and hotspot of the pre-scaled cursor image, in real
// coordinates.
- int16 rW, rH;
- int16 rHotX, rHotY;
+ //int16 rW, rH;
+ //int16 rHotX, rHotY;
// The size and hotspot of the pre-scaled cursor image, in game
// coordinates.
- int16 vW, vH;
- int16 vHotX, vHotY;
+ //int16 vW, vH;
+ //int16 vHotX, vHotY;
- MousePos() : x(0), y(0), w(0), h(0), hotX(0), hotY(0),
+ MousePos() : x(0), y(0), w(0), h(0), hotX(0), hotY(0)/*,
rW(0), rH(0), rHotX(0), rHotY(0), vW(0), vH(0),
- vHotX(0), vHotY(0)
+ vHotX(0), vHotY(0)*/
{ }
};
GLTexture* _cursorTexture;
+ Graphics::Surface _cursorData;
#ifdef USE_RGB_COLOR
Graphics::PixelFormat _cursorFormat;
#endif
@@ -213,7 +230,6 @@ protected:
bool _cursorPaletteDisabled;
MousePos _cursorState;
bool _cursorVisible;
- byte *_cursorData;
uint32 _cursorKeyColor;
int _cursorTargetScale;
bool _cursorNeedsRedraw;
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index aa0a9aa717..6f2ba0df9c 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -44,6 +44,28 @@ OpenGLSdlGraphicsManager::~OpenGLSdlGraphicsManager() {
}
+
+bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) {
+ return
+ (f == OSystem::kFeatureFullscreenMode) ||
+ (f == OSystem::kFeatureIconifyWindow) ||
+ OpenGLGraphicsManager::hasFeature(f);
+}
+
+void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
+ switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ setFullscreenMode(enable);
+ break;
+ case OSystem::kFeatureIconifyWindow:
+ if (enable)
+ SDL_WM_IconifyWindow();
+ break;
+ default:
+ OpenGLGraphicsManager::setFeatureState(f, enable);
+ }
+}
+
#ifdef USE_RGB_COLOR
const Graphics::PixelFormat RGBList[] = {
@@ -202,9 +224,9 @@ void OpenGLSdlGraphicsManager::internUpdateScreen() {
bool OpenGLSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
// Ctrl-Alt-a toggles aspect ratio correction
- /*if (key == 'a') {
+ if (key == 'a') {
beginGFXTransaction();
- setFeatureState(OSystem::kFeatureAspectRatioCorrection, !_videoMode.aspectRatioCorrection);
+ setAspectRatioCorrection(-1);
endGFXTransaction();
#ifdef USE_OSD
char buffer[128];
@@ -222,7 +244,7 @@ bool OpenGLSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
#endif
internUpdateScreen();
return true;
- }*/
+ }
// Ctrl-Alt-f toggles antialiasing
if (key == 'f') {
@@ -329,6 +351,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
_videoMode.hardwareHeight = event.mouse.y;
_screenResized = true;
_transactionDetails.sizeChanged = true;
+ _transactionDetails.newContext = true;
endGFXTransaction();
return true;
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h
index b0bf12cd4d..f11782131c 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.h
+++ b/backends/graphics/openglsdl/openglsdl-graphics.h
@@ -42,6 +42,9 @@ public:
OpenGLSdlGraphicsManager();
virtual ~OpenGLSdlGraphicsManager();
+ virtual bool hasFeature(OSystem::Feature f);
+ virtual void setFeatureState(OSystem::Feature f, bool enable);
+
#ifdef USE_RGB_COLOR
virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
#endif