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:
		
							parent
							
								
									9122446b23
								
							
						
					
					
						commit
						b42725ea20
					
				
					 5 changed files with 99 additions and 13 deletions
				
			
		| 
						 | 
					@ -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)
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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) \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,10 +543,48 @@ 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();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (shState->config().subImageFix)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									/* 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));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									SimpleShader &shader = shState->shaders().simple;
 | 
				
			||||||
 | 
									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)
 | 
									for (size_t i = 0; i < blits.size(); ++i)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					const TileAtlas::Blit &blitOp = blits[i];
 | 
										const TileAtlas::Blit &blitOp = blits[i];
 | 
				
			||||||
| 
						 | 
					@ -556,6 +595,8 @@ struct TilemapPrivate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				GLMeta::subRectImageEnd();
 | 
									GLMeta::subRectImageEnd();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/* Regular tileset */
 | 
								/* Regular tileset */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue