Add config option working around buggy graphics drivers

"subImageFix=true" should fix missing text on radeonsi fglrx
as well as most mobile drivers. Also fixes tileset atlas on
mobile.
This commit is contained in:
Jonas Kulla 2015-01-01 23:38:11 +01:00
parent 9122446b23
commit b42725ea20
5 changed files with 99 additions and 13 deletions

View File

@ -94,6 +94,15 @@
# solidFonts=false # solidFonts=false
# Work around buggy graphics drivers which don't
# properly synchronize texture access, most
# apparent when text doesn't show up or the map
# tileset doesn't render at all
# (default: disabled)
#
# subImageFix=false
# Set the base path of the game to '/path/to/game' # Set the base path of the game to '/path/to/game'
# (default: executable directory) # (default: executable directory)
# #

View File

@ -374,14 +374,46 @@ void Bitmap::stretchBlt(const IntRect &destRect,
if (opacity == 0) if (opacity == 0)
return; return;
if (source.megaSurface()) SDL_Surface *srcSurf = source.megaSurface();
if (srcSurf && shState->config().subImageFix)
{ {
/* Blit from software surface, for broken GL drivers */
Vec2i gpTexSize;
shState->ensureTexSize(sourceRect.w, sourceRect.h, gpTexSize);
shState->bindTex();
GLMeta::subRectImageUpload(srcSurf->w, sourceRect.x, sourceRect.y, 0, 0,
sourceRect.w, sourceRect.h, srcSurf, GL_RGBA);
GLMeta::subRectImageEnd();
SimpleShader &shader = shState->shaders().simple;
shader.bind();
shader.setTranslation(Vec2i());
shader.setTexSize(gpTexSize);
p->pushSetViewport(shader);
p->bindFBO();
Quad &quad = shState->gpQuad();
quad.setTexRect(FloatRect(0, 0, sourceRect.w, sourceRect.h));
quad.setPosRect(destRect);
p->blitQuad(quad);
p->popViewport();
p->addTaintedArea(destRect);
p->onModified();
return;
}
else if (srcSurf)
{
/* Blit from software surface */
/* Don't do transparent blits for now */ /* Don't do transparent blits for now */
if (opacity < 255) if (opacity < 255)
source.ensureNonMega(); source.ensureNonMega();
SDL_Surface *srcSurf = source.megaSurface();
SDL_Rect srcRect = sourceRect; SDL_Rect srcRect = sourceRect;
SDL_Rect dstRect = destRect; SDL_Rect dstRect = destRect;
SDL_Rect btmRect = { 0, 0, width(), height() }; SDL_Rect btmRect = { 0, 0, width(), height() };
@ -405,18 +437,19 @@ void Bitmap::stretchBlt(const IntRect &destRect,
if (bltRect.w == dstRect.w && bltRect.h == dstRect.h) if (bltRect.w == dstRect.w && bltRect.h == dstRect.h)
{ {
/* Dest rectangle lies within bounding box */
TEX::uploadSubImage(destRect.x, destRect.y, TEX::uploadSubImage(destRect.x, destRect.y,
destRect.w, destRect.h, destRect.w, destRect.h,
blitTemp->pixels, GL_RGBA); blitTemp->pixels, GL_RGBA);
} }
else else
{ {
/* Clipped blit */
GLMeta::subRectImageUpload(blitTemp->w, bltRect.x - dstRect.x, bltRect.y - dstRect.y, GLMeta::subRectImageUpload(blitTemp->w, bltRect.x - dstRect.x, bltRect.y - dstRect.y,
bltRect.x, bltRect.y, bltRect.w, bltRect.h, blitTemp, GL_RGBA); bltRect.x, bltRect.y, bltRect.w, bltRect.h, blitTemp, GL_RGBA);
GLMeta::subRectImageEnd(); GLMeta::subRectImageEnd();
} }
SDL_FreeSurface(blitTemp); SDL_FreeSurface(blitTemp);
p->onModified(); p->onModified();
@ -468,7 +501,6 @@ void Bitmap::stretchBlt(const IntRect &destRect,
} }
p->addTaintedArea(destRect); p->addTaintedArea(destRect);
p->onModified(); p->onModified();
} }
@ -1023,7 +1055,7 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
if (fastBlit) if (fastBlit)
{ {
if (squeeze == 1.0) if (squeeze == 1.0 && !shState->config().subImageFix)
{ {
/* Even faster: upload directly to bitmap texture. /* Even faster: upload directly to bitmap texture.
* We have to make sure the posRect lies within the texture * We have to make sure the posRect lies within the texture

View File

@ -153,6 +153,7 @@ Config::Config()
fixedFramerate(0), fixedFramerate(0),
frameSkip(true), frameSkip(true),
solidFonts(false), solidFonts(false),
subImageFix(false),
gameFolder("."), gameFolder("."),
anyAltToggleFS(false), anyAltToggleFS(false),
enableReset(true), enableReset(true),
@ -181,6 +182,7 @@ void Config::read(int argc, char *argv[])
PO_DESC(fixedFramerate, int) \ PO_DESC(fixedFramerate, int) \
PO_DESC(frameSkip, bool) \ PO_DESC(frameSkip, bool) \
PO_DESC(solidFonts, bool) \ PO_DESC(solidFonts, bool) \
PO_DESC(subImageFix, bool) \
PO_DESC(gameFolder, std::string) \ PO_DESC(gameFolder, std::string) \
PO_DESC(anyAltToggleFS, bool) \ PO_DESC(anyAltToggleFS, bool) \
PO_DESC(enableReset, bool) \ PO_DESC(enableReset, bool) \

View File

@ -89,6 +89,8 @@ struct Config
bool solidFonts; bool solidFonts;
bool subImageFix;
std::string gameFolder; std::string gameFolder;
bool anyAltToggleFS; bool anyAltToggleFS;
bool enableReset; bool enableReset;

View File

@ -26,6 +26,7 @@
#include "table.h" #include "table.h"
#include "sharedstate.h" #include "sharedstate.h"
#include "config.h"
#include "glstate.h" #include "glstate.h"
#include "gl-util.h" #include "gl-util.h"
#include "gl-meta.h" #include "gl-meta.h"
@ -542,19 +543,59 @@ struct TilemapPrivate
if (tileset->megaSurface()) if (tileset->megaSurface())
{ {
/* Mega surface tileset */ /* Mega surface tileset */
TEX::bind(atlas.gl.tex);
SDL_Surface *tsSurf = tileset->megaSurface(); SDL_Surface *tsSurf = tileset->megaSurface();
for (size_t i = 0; i < blits.size(); ++i) if (shState->config().subImageFix)
{ {
const TileAtlas::Blit &blitOp = blits[i]; /* Implementation for broken GL drivers */
FBO::bind(atlas.gl.fbo);
glState.blend.pushSet(false);
glState.viewport.pushSet(IntRect(0, 0, atlas.size.x, atlas.size.y));
GLMeta::subRectImageUpload(tsSurf->w, blitOp.src.x, blitOp.src.y, SimpleShader &shader = shState->shaders().simple;
blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h, tsSurf, GL_RGBA); shader.bind();
shader.applyViewportProj();
shader.setTranslation(Vec2i());
Quad &quad = shState->gpQuad();
for (size_t i = 0; i < blits.size(); ++i)
{
const TileAtlas::Blit &blitOp = blits[i];
Vec2i texSize;
shState->ensureTexSize(tsLaneW, blitOp.h, texSize);
shState->bindTex();
GLMeta::subRectImageUpload(tsSurf->w, blitOp.src.x, blitOp.src.y,
0, 0, tsLaneW, blitOp.h, tsSurf, GL_RGBA);
shader.setTexSize(texSize);
quad.setTexRect(FloatRect(0, 0, tsLaneW, blitOp.h));
quad.setPosRect(FloatRect(blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h));
quad.draw();
}
GLMeta::subRectImageEnd();
glState.viewport.pop();
glState.blend.pop();
}
else
{
/* Clean implementation */
TEX::bind(atlas.gl.tex);
for (size_t i = 0; i < blits.size(); ++i)
{
const TileAtlas::Blit &blitOp = blits[i];
GLMeta::subRectImageUpload(tsSurf->w, blitOp.src.x, blitOp.src.y,
blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h, tsSurf, GL_RGBA);
}
GLMeta::subRectImageEnd();
} }
GLMeta::subRectImageEnd();
} }
else else
{ {