OPENGL: Implement fullscreen mode.
svn-id: r51049
This commit is contained in:
parent
014d7b791c
commit
302400a701
6 changed files with 75 additions and 58 deletions
|
@ -77,7 +77,10 @@ GLTexture::GLTexture(byte bpp, GLenum format, GLenum type)
|
|||
_glFormat(format),
|
||||
_glType(type),
|
||||
_textureWidth(0),
|
||||
_textureHeight(0) {
|
||||
_textureHeight(0),
|
||||
_realWidth(0),
|
||||
_realHeight(0),
|
||||
_refresh(false) {
|
||||
|
||||
// Generates the texture ID for GL
|
||||
CHECK_GL_ERROR( glGenTextures(1, &_textureName) );
|
||||
|
@ -91,22 +94,20 @@ GLTexture::GLTexture(byte bpp, GLenum format, GLenum type)
|
|||
}
|
||||
|
||||
GLTexture::~GLTexture() {
|
||||
debug("Destroying texture %u", _textureName);
|
||||
CHECK_GL_ERROR( glDeleteTextures(1, &_textureName) );
|
||||
}
|
||||
|
||||
void GLTexture::refresh() {
|
||||
// Generates the texture ID for GL
|
||||
//CHECK_GL_ERROR( glGenTextures(1, &_textureName) );
|
||||
//updateBuffer(_surface.pixels, _surface.bytesPerPixel, 0, 0, _surface.w, _surface.h);
|
||||
CHECK_GL_ERROR( glGenTextures(1, &_textureName) );
|
||||
_refresh = true;
|
||||
}
|
||||
|
||||
void GLTexture::allocBuffer(GLuint w, GLuint h) {
|
||||
_surface.w = w;
|
||||
_surface.h = h;
|
||||
_surface.bytesPerPixel = _bytesPerPixel;
|
||||
_realWidth = w;
|
||||
_realHeight = h;
|
||||
|
||||
if (w <= _textureWidth && h <= _textureHeight)
|
||||
if (w <= _textureWidth && h <= _textureHeight && !_refresh)
|
||||
// Already allocated a sufficiently large buffer
|
||||
return;
|
||||
|
||||
|
@ -117,9 +118,6 @@ void GLTexture::allocBuffer(GLuint w, GLuint h) {
|
|||
_textureWidth = nextHigher2(w);
|
||||
_textureHeight = nextHigher2(h);
|
||||
}
|
||||
_surface.pitch = _textureWidth * _bytesPerPixel;
|
||||
|
||||
//_surface.create(w, h, _bytesPerPixel);
|
||||
|
||||
// Allocate room for the texture now, but pixel data gets uploaded
|
||||
// later (perhaps with multiple TexSubImage2D operations).
|
||||
|
@ -130,6 +128,11 @@ void GLTexture::allocBuffer(GLuint w, GLuint h) {
|
|||
CHECK_GL_ERROR( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) );
|
||||
CHECK_GL_ERROR( glTexImage2D(GL_TEXTURE_2D, 0, _glFormat,
|
||||
_textureWidth, _textureHeight, 0, _glFormat, _glType, NULL) );
|
||||
|
||||
if (_surface.w != _textureWidth || _surface.h != _textureHeight)
|
||||
_surface.create(_textureWidth, _textureHeight, _bytesPerPixel);
|
||||
|
||||
_refresh = false;
|
||||
}
|
||||
|
||||
void GLTexture::updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, GLuint w, GLuint h) {
|
||||
|
@ -138,15 +141,13 @@ void GLTexture::updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, GLu
|
|||
if (static_cast<int>(w) * _bytesPerPixel == pitch) {
|
||||
CHECK_GL_ERROR( glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
|
||||
_glFormat, _glType, buf) );
|
||||
//memcpy(_surface.pixels, buf, w * pitch);
|
||||
memcpy(_surface.getBasePtr(x, y), buf, h * pitch);
|
||||
} else {
|
||||
// GLES removed the ability to specify pitch, so we
|
||||
// have to do this row by row.
|
||||
const byte* src = static_cast<const byte*>(buf);
|
||||
do {
|
||||
CHECK_GL_ERROR( glTexSubImage2D(GL_TEXTURE_2D, 0, x, y,
|
||||
w, 1, _glFormat, _glType, src) );
|
||||
//memcpy(_surface.pixels, src, pitch);
|
||||
memcpy(_surface.getBasePtr(x, y), src, w * _bytesPerPixel);
|
||||
++y;
|
||||
src += pitch;
|
||||
} while (--h);
|
||||
|
@ -154,19 +155,17 @@ void GLTexture::updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, GLu
|
|||
}
|
||||
|
||||
void GLTexture::fillBuffer(byte x) {
|
||||
byte* tmpbuf = new byte[_surface.h * _surface.w * _bytesPerPixel];
|
||||
memset(tmpbuf, x, _surface.h * _surface.w * _bytesPerPixel);
|
||||
memset(_surface.pixels, x, _surface.h * _surface.pitch);
|
||||
CHECK_GL_ERROR( glBindTexture(GL_TEXTURE_2D, _textureName) );
|
||||
CHECK_GL_ERROR( glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _surface.w, _surface.h,
|
||||
_glFormat, _glType, tmpbuf) );
|
||||
delete[] tmpbuf;
|
||||
_glFormat, _glType, _surface.pixels) );
|
||||
}
|
||||
|
||||
void GLTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
|
||||
CHECK_GL_ERROR( glBindTexture(GL_TEXTURE_2D, _textureName) );
|
||||
|
||||
const GLfloat texWidth = (GLfloat)_surface.w / _textureWidth;//xdiv(_surface.w, _textureWidth);
|
||||
const GLfloat texHeight = (GLfloat)_surface.h / _textureHeight;//xdiv(_surface.h, _textureHeight);
|
||||
const GLfloat texWidth = (GLfloat)_realWidth / _textureWidth;//xdiv(_surface.w, _textureWidth);
|
||||
const GLfloat texHeight = (GLfloat)_realHeight / _textureHeight;//xdiv(_surface.h, _textureHeight);
|
||||
const GLfloat texcoords[] = {
|
||||
0, 0,
|
||||
texWidth, 0,
|
||||
|
|
|
@ -65,13 +65,13 @@ public:
|
|||
virtual void updateBuffer(const void *buf, int pitch, GLuint x, GLuint y,
|
||||
GLuint w, GLuint h);
|
||||
|
||||
virtual void drawTexture() { drawTexture(0, 0, _surface.w, _surface.h); }
|
||||
virtual void drawTexture() { drawTexture(0, 0, _realWidth, _realHeight); }
|
||||
virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
|
||||
|
||||
Graphics::Surface *getSurface() { return &_surface; }
|
||||
|
||||
GLuint getWidth() const { return _surface.w; }
|
||||
GLuint getHeight() const { return _surface.h; }
|
||||
GLuint getWidth() const { return _realWidth; }
|
||||
GLuint getHeight() const { return _realHeight; }
|
||||
GLuint getTextureName() const { return _textureName; }
|
||||
|
||||
protected:
|
||||
|
@ -80,7 +80,10 @@ protected:
|
|||
const GLenum _glType;
|
||||
|
||||
Graphics::Surface _surface;
|
||||
GLuint _realWidth;
|
||||
GLuint _realHeight;
|
||||
GLuint _textureName;
|
||||
GLuint _textureWidth;
|
||||
GLuint _textureHeight;
|
||||
bool _refresh;
|
||||
};
|
||||
|
|
|
@ -226,9 +226,9 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
|
|||
}
|
||||
|
||||
#ifdef USE_RGB_COLOR
|
||||
if (_transactionDetails.sizeChanged || _transactionDetails.formatChanged) {
|
||||
if (_transactionDetails.sizeChanged || _transactionDetails.formatChanged || _transactionDetails.needHotswap) {
|
||||
#else
|
||||
if (_transactionDetails.sizeChanged) {
|
||||
if (_transactionDetails.sizeChanged || _transactionDetails.needHotswap) {
|
||||
#endif
|
||||
unloadGFXMode();
|
||||
if (!loadGFXMode()) {
|
||||
|
@ -243,20 +243,6 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
|
|||
_videoMode.setup = true;
|
||||
_screenChangeCount++;
|
||||
}
|
||||
} else if (_transactionDetails.needHotswap) {
|
||||
//setGraphicsModeIntern();
|
||||
if (!hotswapGFXMode()) {
|
||||
if (_oldVideoMode.setup) {
|
||||
_transactionMode = kTransactionRollback;
|
||||
errors |= endGFXTransaction();
|
||||
}
|
||||
} else {
|
||||
_videoMode.setup = true;
|
||||
_screenChangeCount++;
|
||||
|
||||
if (_transactionDetails.needUpdatescreen)
|
||||
internUpdateScreen();
|
||||
}
|
||||
} else if (_transactionDetails.needUpdatescreen) {
|
||||
//setGraphicsModeIntern();
|
||||
internUpdateScreen();
|
||||
|
@ -365,13 +351,16 @@ void OpenGLGraphicsManager::clearOverlay() {
|
|||
}
|
||||
|
||||
void OpenGLGraphicsManager::grabOverlay(OverlayColor *buf, int pitch) {
|
||||
const Graphics::Surface* surface = _overlayTexture->getSurface();
|
||||
const Graphics::Surface *surface = _overlayTexture->getSurface();
|
||||
assert(surface->bytesPerPixel == sizeof(buf[0]));
|
||||
int h = surface->h;
|
||||
uint w = _overlayTexture->getWidth();
|
||||
uint h = _overlayTexture->getHeight();
|
||||
const byte *src = (byte *)surface->pixels;
|
||||
do {
|
||||
//memcpy(buf, surface->pixels, surface->w * sizeof(buf[0]));
|
||||
memset(buf, 0, surface->w * sizeof(buf[0]));
|
||||
//memset(buf, 0, w * sizeof(buf[0]));
|
||||
memcpy(buf, src, w * sizeof(buf[0]));
|
||||
buf += pitch;
|
||||
src += surface->pitch;
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
|
@ -600,19 +589,19 @@ bool OpenGLGraphicsManager::loadGFXMode() {
|
|||
GLenum type;
|
||||
getGLPixelFormat(_screenFormat, bpp, format, type);
|
||||
_gameTexture = new GLTexture(bpp, format, type);
|
||||
} else
|
||||
} else if (_transactionDetails.newContext)
|
||||
_gameTexture->refresh();
|
||||
|
||||
_overlayFormat = Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0);
|
||||
|
||||
if (!_overlayTexture)
|
||||
_overlayTexture = new GLTexture(2, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
|
||||
else
|
||||
else if (_transactionDetails.newContext)
|
||||
_overlayTexture->refresh();
|
||||
|
||||
if (!_cursorTexture)
|
||||
_cursorTexture = new GLTexture(4, GL_RGBA, GL_UNSIGNED_BYTE);
|
||||
else
|
||||
else if (_transactionDetails.newContext)
|
||||
_cursorTexture->refresh();
|
||||
|
||||
_gameTexture->allocBuffer(_videoMode.screenWidth, _videoMode.screenHeight);
|
||||
|
@ -628,10 +617,6 @@ void OpenGLGraphicsManager::unloadGFXMode() {
|
|||
|
||||
}
|
||||
|
||||
bool OpenGLGraphicsManager::hotswapGFXMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void OpenGLGraphicsManager::setScale(int newScale) {
|
||||
if (newScale == _videoMode.scaleFactor)
|
||||
return;
|
||||
|
|
|
@ -116,6 +116,7 @@ protected:
|
|||
bool sizeChanged;
|
||||
bool needHotswap;
|
||||
bool needUpdatescreen;
|
||||
bool newContext;
|
||||
#ifdef USE_RGB_COLOR
|
||||
bool formatChanged;
|
||||
#endif
|
||||
|
@ -147,7 +148,6 @@ protected:
|
|||
virtual void internUpdateScreen();
|
||||
virtual bool loadGFXMode();
|
||||
virtual void unloadGFXMode();
|
||||
virtual bool hotswapGFXMode();
|
||||
|
||||
virtual void setScale(int newScale);
|
||||
|
||||
|
|
|
@ -139,6 +139,35 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() {
|
|||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
||||
if (_videoMode.fullscreen) {
|
||||
SDL_Rect const* const*availableModes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_OPENGL);
|
||||
const SDL_Rect *bestMode = NULL;
|
||||
uint bestMetric = (uint)-1;
|
||||
while (const SDL_Rect *mode = *availableModes++) {
|
||||
if (mode->w < _videoMode.hardwareWidth)
|
||||
continue;
|
||||
if (mode->h < _videoMode.hardwareHeight)
|
||||
continue;
|
||||
|
||||
uint metric = mode->w * mode->h - _videoMode.hardwareWidth * _videoMode.hardwareHeight;
|
||||
if (metric > bestMetric)
|
||||
continue;
|
||||
|
||||
bestMode = mode;
|
||||
bestMetric = metric;
|
||||
}
|
||||
|
||||
if (bestMode) {
|
||||
_videoMode.hardwareWidth = bestMode->w;
|
||||
_videoMode.hardwareHeight = bestMode->h;
|
||||
} else {
|
||||
_videoMode.fullscreen = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_oldVideoMode.fullscreen != _videoMode.fullscreen)
|
||||
_transactionDetails.newContext = true;
|
||||
|
||||
_hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 32,
|
||||
_videoMode.fullscreen ? (SDL_FULLSCREEN | SDL_OPENGL) : (SDL_OPENGL | SDL_RESIZABLE)
|
||||
);
|
||||
|
@ -164,10 +193,6 @@ void OpenGLSdlGraphicsManager::unloadGFXMode() {
|
|||
}
|
||||
}
|
||||
|
||||
bool OpenGLSdlGraphicsManager::hotswapGFXMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void OpenGLSdlGraphicsManager::internUpdateScreen() {
|
||||
OpenGLGraphicsManager::internUpdateScreen();
|
||||
|
||||
|
@ -216,7 +241,13 @@ bool OpenGLSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
|
|||
}
|
||||
|
||||
void OpenGLSdlGraphicsManager::setFullscreenMode(bool enable) {
|
||||
if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable)
|
||||
return;
|
||||
|
||||
if (_transactionMode == kTransactionActive) {
|
||||
_videoMode.fullscreen = enable;
|
||||
_transactionDetails.needHotswap = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenGLSdlGraphicsManager::isScalerHotkey(const Common::Event &event) {
|
||||
|
|
|
@ -55,7 +55,6 @@ protected:
|
|||
|
||||
virtual bool loadGFXMode();
|
||||
virtual void unloadGFXMode();
|
||||
virtual bool hotswapGFXMode();
|
||||
|
||||
virtual void setFullscreenMode(bool enable);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue