Implement cropped and rescaling texture hack
This commit is contained in:
		
							parent
							
								
									f7a3e3c5d2
								
							
						
					
					
						commit
						9506c05ba6
					
				
					 3 changed files with 177 additions and 3 deletions
				
			
		
							
								
								
									
										125
									
								
								src/bitmap.cpp
									
										
									
									
									
								
							
							
						
						
									
										125
									
								
								src/bitmap.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -43,6 +43,7 @@
 | 
			
		|||
#include "filesystem.h"
 | 
			
		||||
#include "font.h"
 | 
			
		||||
#include "eventthread.h"
 | 
			
		||||
#include "debugwriter.h"
 | 
			
		||||
 | 
			
		||||
#define GUARD_MEGA \
 | 
			
		||||
	{ \
 | 
			
		||||
| 
						 | 
				
			
			@ -100,10 +101,20 @@ struct BitmapPrivate
 | 
			
		|||
	 * ourselves the expensive blending calculation */
 | 
			
		||||
	pixman_region16_t tainted;
 | 
			
		||||
 | 
			
		||||
	bool isCrop;
 | 
			
		||||
	CropTexture cropTex;
 | 
			
		||||
	TEX::ID cropTexTex;
 | 
			
		||||
 | 
			
		||||
	bool isResized;
 | 
			
		||||
	Vec2i resizedSize;
 | 
			
		||||
	TEX::ID resTex;
 | 
			
		||||
 | 
			
		||||
	BitmapPrivate(Bitmap *self)
 | 
			
		||||
	    : self(self),
 | 
			
		||||
	      megaSurface(0),
 | 
			
		||||
	      surface(0)
 | 
			
		||||
	      surface(0),
 | 
			
		||||
	      isCrop(false),
 | 
			
		||||
	      isResized(false)
 | 
			
		||||
	{
 | 
			
		||||
		format = SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -167,7 +178,10 @@ struct BitmapPrivate
 | 
			
		|||
	void bindTexture(ShaderBase &shader)
 | 
			
		||||
	{
 | 
			
		||||
		TEX::bind(gl.tex);
 | 
			
		||||
		shader.setTexSize(Vec2i(gl.width, gl.height));
 | 
			
		||||
		if (isCrop)
 | 
			
		||||
			shader.setTexSize(Vec2i(cropTex.w, cropTex.h));
 | 
			
		||||
		else
 | 
			
		||||
			shader.setTexSize(Vec2i(gl.width, gl.height));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void bindFBO()
 | 
			
		||||
| 
						 | 
				
			
			@ -242,14 +256,114 @@ Bitmap::Bitmap(const char *filename)
 | 
			
		|||
		throw Exception(Exception::SDLError, "Error loading image '%s': %s",
 | 
			
		||||
		                filename, SDL_GetError());
 | 
			
		||||
 | 
			
		||||
	bool isCrop = false;
 | 
			
		||||
	CropTexture cropTex;
 | 
			
		||||
	const std::vector<CropTexture> &crops = shState->config().cropTexs;
 | 
			
		||||
	for (size_t i = 0; i < crops.size(); ++i)
 | 
			
		||||
	{
 | 
			
		||||
		if (crops[i].filename != filename)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		Debug() << "Loading cropped texture:" << filename << crops[i].w << crops[i].h;
 | 
			
		||||
		isCrop = true;
 | 
			
		||||
		cropTex = crops[i];
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p->ensureFormat(imgSurf, SDL_PIXELFORMAT_ABGR8888);
 | 
			
		||||
 | 
			
		||||
	if (imgSurf->w > glState.caps.maxTexSize || imgSurf->h > glState.caps.maxTexSize)
 | 
			
		||||
	SDL_SetSurfaceBlendMode(imgSurf, SDL_BLENDMODE_NONE);
 | 
			
		||||
 | 
			
		||||
	// Try catching too large images, while trying NOT to catch giant tilesets
 | 
			
		||||
	if ((imgSurf->w > glState.caps.maxTexSize || imgSurf->h > glState.caps.maxTexSize) && imgSurf->w != 256 && !isCrop)
 | 
			
		||||
	{
 | 
			
		||||
		Vec2i resSize(imgSurf->w/2, imgSurf->h/2);
 | 
			
		||||
		while (resSize.x > glState.caps.maxTexSize || resSize.y > glState.caps.maxTexSize)
 | 
			
		||||
		{
 | 
			
		||||
			resSize.x = resSize.x/2;
 | 
			
		||||
			resSize.y = resSize.y/2;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Debug() << "Loading image" << filename << "at resolution"
 | 
			
		||||
		        << resSize.x << resSize.y << "down from" << imgSurf->w << imgSurf->h;
 | 
			
		||||
 | 
			
		||||
		// Use texture with halved dimensions instead
 | 
			
		||||
		p = new BitmapPrivate(this);
 | 
			
		||||
		p->isResized = true;
 | 
			
		||||
		p->resizedSize = resSize;
 | 
			
		||||
 | 
			
		||||
		int bpp; Uint32 rm, gm, bm, am;
 | 
			
		||||
		SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ABGR8888, &bpp, &rm, &gm, &bm, &am);
 | 
			
		||||
		SDL_Surface *resImg = SDL_CreateRGBSurface(0, resSize.x, resSize.y, bpp, rm, gm, bm, am);
 | 
			
		||||
 | 
			
		||||
		SDL_BlitScaled(imgSurf, 0, resImg, 0);
 | 
			
		||||
 | 
			
		||||
		TEX::ID tex = TEX::gen();
 | 
			
		||||
		TEX::bind(tex);
 | 
			
		||||
		TEX::uploadImage(resImg->w, resImg->h, resImg->pixels, GL_RGBA);
 | 
			
		||||
		TEX::setRepeat(false);
 | 
			
		||||
		TEX::setSmooth(true);
 | 
			
		||||
 | 
			
		||||
		p->resTex = tex;
 | 
			
		||||
		p->gl.tex = tex;
 | 
			
		||||
		p->gl.width = imgSurf->w;
 | 
			
		||||
		p->gl.height = imgSurf->h;
 | 
			
		||||
 | 
			
		||||
		SDL_FreeSurface(imgSurf);
 | 
			
		||||
		SDL_FreeSurface(resImg);
 | 
			
		||||
	}
 | 
			
		||||
	else if ((imgSurf->h > glState.caps.maxTexSize) && !isCrop) // Too large tilesets go here
 | 
			
		||||
	{
 | 
			
		||||
		/* Mega surface */
 | 
			
		||||
		p = new BitmapPrivate(this);
 | 
			
		||||
		p->megaSurface = imgSurf;
 | 
			
		||||
	}
 | 
			
		||||
	else if (isCrop)
 | 
			
		||||
	{
 | 
			
		||||
		p = new BitmapPrivate(this);
 | 
			
		||||
		p->cropTex = cropTex;
 | 
			
		||||
 | 
			
		||||
		Vec2i resSize(cropTex.w, cropTex.h);
 | 
			
		||||
		while (resSize.x > glState.caps.maxTexSize || resSize.y > glState.caps.maxTexSize)
 | 
			
		||||
		{
 | 
			
		||||
			resSize.x = resSize.x/2;
 | 
			
		||||
			resSize.y = resSize.y/2;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		TEX::ID tex = TEX::gen();
 | 
			
		||||
		TEX::bind(tex);
 | 
			
		||||
		TEX::setRepeat(false);
 | 
			
		||||
		TEX::setSmooth(false);
 | 
			
		||||
 | 
			
		||||
		if (resSize == Vec2i(cropTex.w, cropTex.h))
 | 
			
		||||
		{
 | 
			
		||||
			TEX::allocEmpty(cropTex.w, cropTex.h);
 | 
			
		||||
			GLMeta::subRectImageUpload(imgSurf->w, 0, 0, 0, 0, cropTex.w, cropTex.h, imgSurf, GL_RGBA);
 | 
			
		||||
			GLMeta::subRectImageEnd();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			int bpp; Uint32 rm, gm, bm, am;
 | 
			
		||||
			SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ABGR8888, &bpp, &rm, &gm, &bm, &am);
 | 
			
		||||
			SDL_Surface *resImg = SDL_CreateRGBSurface(0, resSize.x, resSize.y, bpp, rm, gm, bm, am);
 | 
			
		||||
 | 
			
		||||
			IntRect src(0, 0, cropTex.w, cropTex.h);
 | 
			
		||||
			SDL_BlitScaled(imgSurf, &src, resImg, 0);
 | 
			
		||||
			TEX::uploadImage(resSize.x, resSize.y, resImg->pixels, GL_RGBA);
 | 
			
		||||
 | 
			
		||||
			SDL_FreeSurface(resImg);
 | 
			
		||||
 | 
			
		||||
			Debug() << "Loading cropped image" << filename << "at resolution"
 | 
			
		||||
			        << resSize.x << resSize.y << "down from" << cropTex.w << cropTex.h;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		p->cropTexTex = tex;
 | 
			
		||||
 | 
			
		||||
		p->gl.tex = tex;
 | 
			
		||||
		p->gl.width = imgSurf->w;
 | 
			
		||||
		p->gl.height = imgSurf->h;
 | 
			
		||||
		SDL_FreeSurface(imgSurf);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		/* Regular surface */
 | 
			
		||||
| 
						 | 
				
			
			@ -274,6 +388,7 @@ Bitmap::Bitmap(const char *filename)
 | 
			
		|||
		SDL_FreeSurface(imgSurf);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p->isCrop = isCrop;
 | 
			
		||||
	p->addTaintedArea(rect());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1230,6 +1345,10 @@ void Bitmap::releaseResources()
 | 
			
		|||
{
 | 
			
		||||
	if (p->megaSurface)
 | 
			
		||||
		SDL_FreeSurface(p->megaSurface);
 | 
			
		||||
	else if (p->isCrop)
 | 
			
		||||
		TEX::del(p->cropTexTex);
 | 
			
		||||
	else if (p->isResized)
 | 
			
		||||
		TEX::del(p->resTex);
 | 
			
		||||
	else
 | 
			
		||||
		shState->texPool().release(p->gl);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -261,6 +261,53 @@ void Config::read(int argc, char *argv[])
 | 
			
		|||
		customDataPath = prefPath(dataPathOrg.c_str(), dataPathApp.c_str());
 | 
			
		||||
 | 
			
		||||
	commonDataPath = prefPath(".", "mkxp");
 | 
			
		||||
 | 
			
		||||
	/* parse cropped textures config */
 | 
			
		||||
	std::string cropTexFile;
 | 
			
		||||
	if (!readFile("croptextures", cropTexFile))
 | 
			
		||||
	{
 | 
			
		||||
		Debug() << "Couldn't read croptextures config file";
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	size_t lineStart = 0;
 | 
			
		||||
	bool atEnd = false;
 | 
			
		||||
 | 
			
		||||
	while (!atEnd)
 | 
			
		||||
	{
 | 
			
		||||
		CropTexture tex;
 | 
			
		||||
 | 
			
		||||
		size_t fnEnd = cropTexFile.find('"', lineStart+1);
 | 
			
		||||
		size_t numSep = cropTexFile.find(' ', fnEnd+2);
 | 
			
		||||
		size_t lineEnd = cropTexFile.find('\n', numSep);
 | 
			
		||||
 | 
			
		||||
		if (fnEnd == std::string::npos || numSep == std::string::npos)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		if (lineEnd == std::string::npos)
 | 
			
		||||
		{
 | 
			
		||||
			lineEnd = cropTexFile.size();
 | 
			
		||||
			atEnd = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		try
 | 
			
		||||
		{
 | 
			
		||||
			tex.filename = cropTexFile.substr(lineStart+1, fnEnd-(lineStart+1));
 | 
			
		||||
			tex.w = atoi(cropTexFile.substr(fnEnd+2, numSep-(fnEnd+2)).c_str());
 | 
			
		||||
			tex.h = atoi(cropTexFile.substr(numSep+1, lineEnd-(numSep+1)).c_str());
 | 
			
		||||
		}
 | 
			
		||||
		catch (...)
 | 
			
		||||
		{
 | 
			
		||||
			Debug() << "Couldn't parse croptextures config file";
 | 
			
		||||
			cropTexs.clear();
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cropTexs.push_back(tex);
 | 
			
		||||
		Debug() << "Parsed:" << tex.filename << tex.w << tex.h;
 | 
			
		||||
 | 
			
		||||
		lineStart = lineEnd+1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static std::string baseName(const std::string &path)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,12 @@
 | 
			
		|||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
struct CropTexture
 | 
			
		||||
{
 | 
			
		||||
	std::string filename;
 | 
			
		||||
	int w, h;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Config
 | 
			
		||||
{
 | 
			
		||||
	int rgssVersion;
 | 
			
		||||
| 
						 | 
				
			
			@ -89,6 +95,8 @@ struct Config
 | 
			
		|||
	std::string customDataPath;
 | 
			
		||||
	std::string commonDataPath;
 | 
			
		||||
 | 
			
		||||
	std::vector<CropTexture> cropTexs;
 | 
			
		||||
 | 
			
		||||
	Config();
 | 
			
		||||
 | 
			
		||||
	void read(int argc, char *argv[]);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue