Skip to content

Commit

Permalink
OPENGL: Add OSD support.
Browse files Browse the repository at this point in the history
  • Loading branch information
Johannes Schickel committed Oct 19, 2013
1 parent 5ce830b commit cc9c991
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 1 deletion.
131 changes: 130 additions & 1 deletion backends/graphics/opengl/opengl-graphics.cpp
Expand Up @@ -29,8 +29,16 @@
#include "common/textconsole.h"
#include "common/translation.h"
#include "common/algorithm.h"
#ifdef USE_OSD
#include "common/tokenizer.h"
#include "common/rect.h"
#endif

#include "graphics/conversion.h"
#ifdef USE_OSD
#include "graphics/fontman.h"
#include "graphics/font.h"
#endif

namespace OpenGL {

Expand All @@ -42,14 +50,21 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
_overlayVisible(false), _cursor(nullptr),
_cursorX(0), _cursorY(0), _cursorHotspotX(0), _cursorHotspotY(0), _cursorHotspotXScaled(0),
_cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0), _cursorKeyColor(0),
_cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false) {
_cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false)
#ifdef USE_OSD
, _osdAlpha(0), _osdFadeStartTime(0), _osd(nullptr)
#endif
{
memset(_gamePalette, 0, sizeof(_gamePalette));
}

OpenGLGraphicsManager::~OpenGLGraphicsManager() {
delete _gameScreen;
delete _overlay;
delete _cursor;
#ifdef USE_OSD
delete _osd;
#endif
}

bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) {
Expand Down Expand Up @@ -137,6 +152,12 @@ bool OpenGLGraphicsManager::setGraphicsMode(int mode) {
if (_cursor) {
_cursor->enableLinearFiltering(mode == GFX_LINEAR);
}

#ifdef USE_OSD
if (_osd) {
_osd->enableLinearFiltering(mode == GFX_LINEAR);
}
#endif
return true;

default:
Expand Down Expand Up @@ -374,6 +395,34 @@ void OpenGLGraphicsManager::updateScreen() {

glPopMatrix();
}

#ifdef USE_OSD
// Fourth step: Draw the OSD.
if (_osdAlpha > 0) {
Common::StackLock lock(_osdMutex);

// Update alpha value.
const int diff = g_system->getMillis(false) - _osdFadeStartTime;
if (diff > 0) {
if (diff >= kOSDFadeOutDuration) {
// Back to full transparency.
_osdAlpha = 0;
} else {
// Do a fade out.
_osdAlpha = kOSDInitialAlpha - diff * kOSDInitialAlpha / kOSDFadeOutDuration;
}
}

// Set the OSD transparency.
GLCALL(glColor4f(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f));

// Draw the OSD texture.
_osd->draw(0, 0, _outputScreenWidth, _outputScreenHeight);

// Reset color.
GLCALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f));
}
#endif
}

Graphics::Surface *OpenGLGraphicsManager::lockScreen() {
Expand Down Expand Up @@ -617,6 +666,59 @@ void OpenGLGraphicsManager::setCursorPalette(const byte *colors, uint start, uin
}

void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) {
#ifdef USE_OSD
// HACK: Actually no client code should use graphics functions from
// another thread. But the MT-32 emulator still does, thus we need to
// make sure this doesn't happen while a updateScreen call is done.
Common::StackLock lock(_osdMutex);

// Slip up the lines.
Common::Array<Common::String> osdLines;
Common::StringTokenizer tokenizer(msg, "\n");
while (!tokenizer.empty()) {
osdLines.push_back(tokenizer.nextToken());
}

// Do the actual drawing like the SDL backend.
const Graphics::Font *font = getFontOSD();
Graphics::Surface *dst = _osd->getSurface();
_osd->fill(0);
_osd->flagDirty();

// 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
width = MIN<int>(width, dst->w);
height = MIN<int>(height, dst->h);

int dstX = (dst->w - width) / 2;
int dstY = (dst->h - height) / 2;

// Draw a dark gray rect.
const uint32 color = dst->format.RGBToColor(40, 40, 40);
dst->fillRect(Common::Rect(dstX, dstY, dstX + width, dstY + height), color);

// Render the message, centered, and in white
const uint32 white = dst->format.RGBToColor(255, 255, 255);
for (uint i = 0; i < osdLines.size(); ++i) {
font->drawString(dst, osdLines[i],
dstX, dstY + i * lineHeight + vOffset + lineSpacing, width,
white, Graphics::kTextAlignCenter);
}

// Init the OSD display parameters.
_osdAlpha = kOSDInitialAlpha;
_osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay;
#endif
}

void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) {
Expand Down Expand Up @@ -672,6 +774,21 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
_overlay->allocate(overlayWidth, overlayHeight);
_overlay->fill(0);

#ifdef USE_OSD
if (!_osd || _osd->getFormat() != _defaultFormatAlpha) {
delete _osd;
_osd = nullptr;

GLenum glIntFormat, glFormat, glType;
const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType);
assert(supported);
_osd = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha);
_osd->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR);
}
_osd->allocate(_outputScreenWidth, _outputScreenHeight);
_osd->fill(0);
#endif

// Re-setup the scaling for the screen and cursor
recalculateDisplayArea();
recalculateCursorScaling();
Expand Down Expand Up @@ -729,6 +846,12 @@ void OpenGLGraphicsManager::notifyContextChange(const Graphics::PixelFormat &def
if (_cursor) {
_cursor->recreateInternalTexture();
}

#ifdef USE_OSD
if (_osd) {
_osd->recreateInternalTexture();
}
#endif
}

void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) {
Expand Down Expand Up @@ -923,4 +1046,10 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
}
}

#ifdef USE_OSD
const Graphics::Font *OpenGLGraphicsManager::getFontOSD() {
return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont);
}
#endif

} // End of namespace OpenGL
48 changes: 48 additions & 0 deletions backends/graphics/opengl/opengl-graphics.h
Expand Up @@ -27,9 +27,19 @@
#include "backends/graphics/graphics.h"

#include "common/frac.h"
#include "common/mutex.h"

namespace Graphics {
class Font;
} // End of namespace Graphics

namespace OpenGL {

// HACK: We use glColor in the OSD code. This might not be working on GL ES but
// we still enable it because Tizen already shipped with it. Also, the
// SurfaceSDL backend enables it and disabling it can cause issues in sdl.cpp.
#define USE_OSD 1

class Texture;

enum {
Expand Down Expand Up @@ -415,6 +425,44 @@ class OpenGLGraphicsManager : public GraphicsManager {
* The special cursor palette in case enabled.
*/
byte _cursorPalette[3 * 256];

#ifdef USE_OSD
//
// OSD
//
protected:
/**
* Returns the font used for on screen display
*/
virtual const Graphics::Font *getFontOSD();

private:
/**
* The OSD's contents.
*/
Texture *_osd;

/**
* Current opacity level of the OSD.
*/
uint8 _osdAlpha;

/**
* When fading the OSD has started.
*/
uint32 _osdFadeStartTime;

/**
* Mutex to allow displayMessageOnOSD to be used from the audio thread.
*/
Common::Mutex _osdMutex;

enum {
kOSDFadeOutDelay = 2 * 1000,
kOSDFadeOutDuration = 500,
kOSDInitialAlpha = 80
};
#endif
};

} // End of namespace OpenGL
Expand Down

0 comments on commit cc9c991

Please sign in to comment.