OPENGL: Update the OSD texture when visible while the output mode changes.
This fixes annoying graphics glitches, which occured sometimes when resizing the Window.
This commit is contained in:
parent
3c656916f1
commit
372af10a7b
2 changed files with 69 additions and 56 deletions
|
@ -33,6 +33,9 @@
|
||||||
#include "common/file.h"
|
#include "common/file.h"
|
||||||
#include "common/mutex.h"
|
#include "common/mutex.h"
|
||||||
#include "common/translation.h"
|
#include "common/translation.h"
|
||||||
|
#ifdef USE_OSD
|
||||||
|
#include "common/tokenizer.h"
|
||||||
|
#endif
|
||||||
#include "graphics/font.h"
|
#include "graphics/font.h"
|
||||||
#include "graphics/fontman.h"
|
#include "graphics/fontman.h"
|
||||||
|
|
||||||
|
@ -643,61 +646,12 @@ void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) {
|
||||||
assert(_transactionMode == kTransactionNone);
|
assert(_transactionMode == kTransactionNone);
|
||||||
assert(msg);
|
assert(msg);
|
||||||
|
|
||||||
// The font we are going to use:
|
|
||||||
const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kOSDFont);
|
|
||||||
|
|
||||||
if (_osdSurface.w != _osdTexture->getWidth() || _osdSurface.h != _osdTexture->getHeight())
|
|
||||||
_osdSurface.create(_osdTexture->getWidth(), _osdTexture->getHeight(), 2);
|
|
||||||
else
|
|
||||||
// Clear everything
|
|
||||||
memset(_osdSurface.pixels, 0, _osdSurface.h * _osdSurface.pitch);
|
|
||||||
|
|
||||||
// Split the message into separate lines.
|
// Split the message into separate lines.
|
||||||
Common::Array<Common::String> lines;
|
_osdLines.clear();
|
||||||
const char *ptr;
|
|
||||||
for (ptr = msg; *ptr; ++ptr) {
|
|
||||||
if (*ptr == '\n') {
|
|
||||||
lines.push_back(Common::String(msg, ptr - msg));
|
|
||||||
msg = ptr + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lines.push_back(Common::String(msg, ptr - msg));
|
|
||||||
|
|
||||||
// Determine a rect which would contain the message string (clipped to the
|
Common::StringTokenizer tokenizer(msg, "\n");
|
||||||
// screen dimensions).
|
while (!tokenizer.empty())
|
||||||
const int vOffset = 6;
|
_osdLines.push_back(tokenizer.nextToken());
|
||||||
const int lineSpacing = 1;
|
|
||||||
const int lineHeight = font->getFontHeight() + 2 * lineSpacing;
|
|
||||||
int width = 0;
|
|
||||||
int height = lineHeight * lines.size() + 2 * vOffset;
|
|
||||||
for (uint i = 0; i < lines.size(); i++) {
|
|
||||||
width = MAX(width, font->getStringWidth(lines[i]) + 14);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clip the rect
|
|
||||||
if (width > _osdSurface.w)
|
|
||||||
width = _osdSurface.w;
|
|
||||||
if (height > _osdSurface.h)
|
|
||||||
height = _osdSurface.h;
|
|
||||||
|
|
||||||
int dstX = (_osdSurface.w - width) / 2;
|
|
||||||
int dstY = (_osdSurface.h - height) / 2;
|
|
||||||
|
|
||||||
// Draw a dark gray rect
|
|
||||||
uint16 color = 0x294B;
|
|
||||||
uint16 *dst = (uint16 *)_osdSurface.pixels + dstY * _osdSurface.w + dstX;
|
|
||||||
for (int i = 0; i < height; i++) {
|
|
||||||
for (int j = 0; j < width; j++)
|
|
||||||
dst[j] = color;
|
|
||||||
dst += _osdSurface.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render the message, centered, and in white
|
|
||||||
for (uint i = 0; i < lines.size(); i++) {
|
|
||||||
font->drawString(&_osdSurface, lines[i],
|
|
||||||
dstX, dstY + i * lineHeight + vOffset + lineSpacing, width,
|
|
||||||
0xFFFF, Graphics::kTextAlignCenter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request update of the texture
|
// Request update of the texture
|
||||||
_requireOSDUpdate = true;
|
_requireOSDUpdate = true;
|
||||||
|
@ -1071,9 +1025,7 @@ void OpenGLGraphicsManager::internUpdateScreen() {
|
||||||
#ifdef USE_OSD
|
#ifdef USE_OSD
|
||||||
if (_osdAlpha > 0) {
|
if (_osdAlpha > 0) {
|
||||||
if (_requireOSDUpdate) {
|
if (_requireOSDUpdate) {
|
||||||
// Update the texture
|
updateOSD();
|
||||||
_osdTexture->updateBuffer(_osdSurface.pixels, _osdSurface.pitch, 0, 0,
|
|
||||||
_osdSurface.w, _osdSurface.h);
|
|
||||||
_requireOSDUpdate = false;
|
_requireOSDUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1229,6 +1181,9 @@ void OpenGLGraphicsManager::loadTextures() {
|
||||||
_osdTexture->refresh();
|
_osdTexture->refresh();
|
||||||
|
|
||||||
_osdTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight);
|
_osdTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight);
|
||||||
|
|
||||||
|
// Update the OSD in case it is used right now
|
||||||
|
_requireOSDUpdate = true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1395,4 +1350,52 @@ void OpenGLGraphicsManager::switchDisplayMode(int mode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_OSD
|
||||||
|
void OpenGLGraphicsManager::updateOSD() {
|
||||||
|
// The font we are going to use:
|
||||||
|
const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kOSDFont);
|
||||||
|
|
||||||
|
if (_osdSurface.w != _osdTexture->getWidth() || _osdSurface.h != _osdTexture->getHeight())
|
||||||
|
_osdSurface.create(_osdTexture->getWidth(), _osdTexture->getHeight(), 2);
|
||||||
|
else
|
||||||
|
// Clear everything
|
||||||
|
memset(_osdSurface.pixels, 0, _osdSurface.h * _osdSurface.pitch);
|
||||||
|
|
||||||
|
// Determine a rect which would contain the message string (clipped to the
|
||||||
|
// screen dimensions).
|
||||||
|
const int vOffset = 6;
|
||||||
|
const int lineSpacing = 1;
|
||||||
|
const int lineHeight = font->getFontHeight() + 2 * lineSpacing;
|
||||||
|
int width = 0;
|
||||||
|
int height = lineHeight * _osdLines.size() + 2 * vOffset;
|
||||||
|
for (uint i = 0; i < _osdLines.size(); i++) {
|
||||||
|
width = MAX(width, font->getStringWidth(_osdLines[i]) + 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clip the rect
|
||||||
|
if (width > _osdSurface.w)
|
||||||
|
width = _osdSurface.w;
|
||||||
|
if (height > _osdSurface.h)
|
||||||
|
height = _osdSurface.h;
|
||||||
|
|
||||||
|
int dstX = (_osdSurface.w - width) / 2;
|
||||||
|
int dstY = (_osdSurface.h - height) / 2;
|
||||||
|
|
||||||
|
// Draw a dark gray rect
|
||||||
|
const uint16 color = 0x294B;
|
||||||
|
_osdSurface.fillRect(Common::Rect(dstX, dstY, dstX + width, dstY + height), color);
|
||||||
|
|
||||||
|
// Render the message, centered, and in white
|
||||||
|
for (uint i = 0; i < _osdLines.size(); i++) {
|
||||||
|
font->drawString(&_osdSurface, _osdLines[i],
|
||||||
|
dstX, dstY + i * lineHeight + vOffset + lineSpacing, width,
|
||||||
|
0xFFFF, Graphics::kTextAlignCenter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the texture
|
||||||
|
_osdTexture->updateBuffer(_osdSurface.pixels, _osdSurface.pitch, 0, 0,
|
||||||
|
_osdSurface.w, _osdSurface.h);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -296,6 +296,16 @@ protected:
|
||||||
virtual bool saveScreenshot(const char *filename);
|
virtual bool saveScreenshot(const char *filename);
|
||||||
|
|
||||||
#ifdef USE_OSD
|
#ifdef USE_OSD
|
||||||
|
/**
|
||||||
|
* The OSD contents.
|
||||||
|
*/
|
||||||
|
Common::Array<Common::String> _osdLines;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the OSD texture / surface.
|
||||||
|
*/
|
||||||
|
void updateOSD();
|
||||||
|
|
||||||
GLTexture *_osdTexture;
|
GLTexture *_osdTexture;
|
||||||
Graphics::Surface _osdSurface;
|
Graphics::Surface _osdSurface;
|
||||||
uint8 _osdAlpha;
|
uint8 _osdAlpha;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue