diff --git a/mkxp.pro b/mkxp.pro index c93abd5..35079c7 100644 --- a/mkxp.pro +++ b/mkxp.pro @@ -124,7 +124,8 @@ HEADERS += \ src/al-util.h \ src/boost-hash.h \ src/debugwriter.h \ - src/gl-fun.h + src/gl-fun.h \ + src/gl-meta.h SOURCES += \ src/main.cpp \ diff --git a/src/bitmap.cpp b/src/bitmap.cpp index 21a6585..a040d7d 100644 --- a/src/bitmap.cpp +++ b/src/bitmap.cpp @@ -30,6 +30,7 @@ #include #include "gl-util.h" +#include "gl-meta.h" #include "quad.h" #include "quadarray.h" #include "transform.h" @@ -875,25 +876,38 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align) * there's nothing to upload to begin with */ if (SDL_IntersectRect(&btmRect, &txtRect, &inters)) { + bool subImage = false; + int subSrcX = 0, subSrcY = 0; + if (inters.w != txtRect.w || inters.h != txtRect.h) { /* Clip the text surface */ - SDL_Rect clipSrc = inters; - clipSrc.x -= txtRect.x; - clipSrc.y -= txtRect.y; + subSrcX = inters.x - txtRect.x; + subSrcY = inters.y - txtRect.y; + subImage = true; posRect.x = inters.x; posRect.y = inters.y; posRect.w = inters.w; posRect.h = inters.h; - - PixelStore::setupSubImage(txtSurf->w, clipSrc.x, clipSrc.y); } TEX::bind(p->gl.tex); - TEX::uploadSubImage(posRect.x, posRect.y, posRect.w, posRect.h, txtSurf->pixels, GL_BGRA); - PixelStore::reset(); + if (!subImage) + { + TEX::uploadSubImage(posRect.x, posRect.y, + posRect.w, posRect.h, + txtSurf->pixels, GL_BGRA); + } + else + { + GLMeta::subRectImageUpload(txtSurf->w, subSrcX, subSrcY, + posRect.x, posRect.y, + posRect.w, posRect.h, + txtSurf, GL_BGRA); + GLMeta::subRectImageFinish(); + } } } else diff --git a/src/gl-fun.cpp b/src/gl-fun.cpp index f95534b..637c116 100644 --- a/src/gl-fun.cpp +++ b/src/gl-fun.cpp @@ -95,6 +95,9 @@ void initGLFunctions() else parseExtensionsCompat(gl.GetString, ext); + // FIXME: Set based on GL kind + gl.unpack_subimage = true; + #define HAVE_EXT(_ext) ext.contains("GL_" #_ext) if (!HAVE_EXT(ARB_framebuffer_object)) diff --git a/src/gl-fun.h b/src/gl-fun.h index 7f20ae1..611d7e3 100644 --- a/src/gl-fun.h +++ b/src/gl-fun.h @@ -146,6 +146,8 @@ struct GLFunctions GL_VAO_FUN GL_DEBUG_KHR_FUN + bool unpack_subimage; + #undef GL_FUN }; diff --git a/src/gl-meta.h b/src/gl-meta.h new file mode 100644 index 0000000..e29498e --- /dev/null +++ b/src/gl-meta.h @@ -0,0 +1,65 @@ +/* +** gl-meta.h +** +** This file is part of mkxp. +** +** Copyright (C) 2014 Jonas Kulla +** +** mkxp is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 2 of the License, or +** (at your option) any later version. +** +** mkxp is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with mkxp. If not, see . +*/ + +#ifndef GLMETA_H +#define GLMETA_H + +#include "gl-fun.h" +#include "gl-util.h" + +#include + +namespace GLMeta +{ + +inline void subRectImageUpload(GLint srcW, GLint srcX, GLint srcY, + GLint dstX, GLint dstY, GLsizei dstW, GLsizei dstH, + SDL_Surface *src, GLenum format) +{ + if (gl.unpack_subimage) + { + PixelStore::setupSubImage(srcW, srcX, srcY); + TEX::uploadSubImage(dstX, dstY, dstW, dstH, src->pixels, format); + } + else + { + SDL_PixelFormat *form = src->format; + SDL_Surface *tmp = SDL_CreateRGBSurface(0, dstW, dstH, form->BitsPerPixel, + form->Rmask, form->Gmask, form->Bmask, form->Amask); + SDL_Rect srcRect = { srcX, srcY, dstW, dstH }; + + SDL_BlitSurface(src, &srcRect, tmp, 0); + + TEX::uploadSubImage(dstX, dstY, dstW, dstH, tmp->pixels, format); + + SDL_FreeSurface(tmp); + } +} + +inline void subRectImageFinish() +{ + if (gl.unpack_subimage) + PixelStore::reset(); +} + +} + +#endif // GLMETA_H diff --git a/src/tilemap.cpp b/src/tilemap.cpp index 89cc7dd..bc74838 100644 --- a/src/tilemap.cpp +++ b/src/tilemap.cpp @@ -28,6 +28,7 @@ #include "sharedstate.h" #include "glstate.h" #include "gl-util.h" +#include "gl-meta.h" #include "global-ibo.h" #include "etc-internal.h" #include "quadarray.h" @@ -616,12 +617,11 @@ struct TilemapPrivate { const TileAtlas::Blit &blitOp = blits[i]; - PixelStore::setupSubImage(tsSurf->w, blitOp.src.x, blitOp.src.y); - - TEX::uploadSubImage(blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h, tsSurf->pixels, GL_RGBA); + GLMeta::subRectImageUpload(tsSurf->w, blitOp.src.x, blitOp.src.y, + blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h, tsSurf, GL_RGBA); } - PixelStore::reset(); + GLMeta::subRectImageFinish(); } else {