From a26c73930d36d79e6080ac0116b42d863ae350ef Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Wed, 16 Jul 2014 04:48:40 +0200 Subject: [PATCH] GLMeta: Add framebuffer blitting support --- src/bitmap.cpp | 46 +++++++-------- src/gl-fun.h | 7 +-- src/gl-meta.cpp | 80 ++++++++++++++++++++++++++ src/gl-meta.h | 10 ++++ src/gl-util.h | 84 ++------------------------- src/graphics.cpp | 144 ++++++++++++++++++++++++++++------------------- src/shader.cpp | 10 ++-- src/tilemap.cpp | 23 +++++--- src/window.cpp | 2 +- 9 files changed, 225 insertions(+), 181 deletions(-) diff --git a/src/bitmap.cpp b/src/bitmap.cpp index a040d7d..3938dc1 100644 --- a/src/bitmap.cpp +++ b/src/bitmap.cpp @@ -150,7 +150,7 @@ struct BitmapPrivate void bindFBO() { - FBO::bind(gl.fbo, FBO::Draw); + FBO::bind(gl.fbo, FBO::Generic); } void pushSetViewport(ShaderBase &shader) const @@ -384,11 +384,10 @@ void Bitmap::stretchBlt(const IntRect &destRect, if (opacity == 255 && !p->touchesTaintedArea(destRect)) { /* Fast blit */ - FBO::bind(source.p->gl.fbo, FBO::Read); - FBO::bind(p->gl.fbo, FBO::Draw); - - FBO::blit(sourceRect.x, sourceRect.y, sourceRect.w, sourceRect.h, - destRect.x, destRect.y, destRect.w, destRect.h); + GLMeta::blitBegin(p->gl); + GLMeta::blitSource(source.p->gl); + GLMeta::blitRectangle(sourceRect, destRect); + GLMeta::blitFinish(); } else { @@ -397,9 +396,10 @@ void Bitmap::stretchBlt(const IntRect &destRect, TEXFBO &gpTex = shState->gpTexFBO(destRect.w, destRect.h); - FBO::bind(gpTex.fbo, FBO::Draw); - FBO::bind(p->gl.fbo, FBO::Read); - FBO::blit(destRect.x, destRect.y, 0, 0, destRect.w, destRect.h); + GLMeta::blitBegin(gpTex); + GLMeta::blitSource(p->gl); + GLMeta::blitRectangle(destRect, Vec2i()); + GLMeta::blitFinish(); FloatRect bltSubRect((float) sourceRect.x / source.width(), (float) sourceRect.y / source.height(), @@ -544,7 +544,7 @@ void Bitmap::blur() glState.viewport.pushSet(IntRect(0, 0, width(), height())); TEX::bind(p->gl.tex); - FBO::bind(auxTex.fbo, FBO::Draw); + FBO::bind(auxTex.fbo, FBO::Generic); pass1.bind(); pass1.setTexSize(Vec2i(width(), height())); @@ -553,7 +553,7 @@ void Bitmap::blur() quad.draw(); TEX::bind(auxTex.tex); - FBO::bind(p->gl.fbo, FBO::Draw); + p->bindFBO(); pass2.bind(); pass2.setTexSize(Vec2i(width(), height())); @@ -625,7 +625,7 @@ void Bitmap::radialBlur(int angle, int divisions) TEXFBO newTex = shState->texPool().request(_width, _height); - FBO::bind(newTex.fbo, FBO::Draw); + FBO::bind(newTex.fbo, FBO::Generic); glState.clearColor.pushSet(Vec4()); FBO::clear(); @@ -698,7 +698,7 @@ Color Bitmap::getPixel(int x, int y) const { p->allocSurface(); - FBO::bind(p->gl.fbo, FBO::Read); + FBO::bind(p->gl.fbo, FBO::Generic); glState.viewport.pushSet(IntRect(0, 0, width(), height())); @@ -764,7 +764,7 @@ void Bitmap::hueChange(int hue) shader.bind(); shader.setHueAdjust(hueAdj); - FBO::bind(newTex.fbo, FBO::Draw); + FBO::bind(newTex.fbo, FBO::Generic); p->pushSetViewport(shader); p->bindTexture(shader); @@ -918,12 +918,11 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align) TEX::bind(gpTF.tex); TEX::uploadSubImage(0, 0, txtSurf->w, txtSurf->h, txtSurf->pixels, GL_BGRA); - FBO::bind(gpTF.fbo, FBO::Read); - p->bindFBO(); - - FBO::blit(0, 0, txtSurf->w, txtSurf->h, - posRect.x, posRect.y, posRect.w, posRect.h, - FBO::Linear); + GLMeta::blitBegin(p->gl); + GLMeta::blitSource(gpTF); + GLMeta::blitRectangle(IntRect(0, 0, txtSurf->w, txtSurf->h), + posRect, FBO::Linear); + GLMeta::blitFinish(); } } else @@ -932,9 +931,10 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align) * buffer we're about to render to */ TEXFBO &gpTex2 = shState->gpTexFBO(posRect.w, posRect.h); - FBO::bind(gpTex2.fbo, FBO::Draw); - FBO::bind(p->gl.fbo, FBO::Read); - FBO::blit(posRect.x, posRect.y, 0, 0, posRect.w, posRect.h); + GLMeta::blitBegin(gpTex2); + GLMeta::blitSource(p->gl); + GLMeta::blitRectangle(posRect, Vec2i()); + GLMeta::blitFinish(); FloatRect bltRect(0, 0, (float) gpTexSize.x / gpTex2.width, diff --git a/src/gl-fun.h b/src/gl-fun.h index 64bdff4..12307df 100644 --- a/src/gl-fun.h +++ b/src/gl-fun.h @@ -120,12 +120,7 @@ typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, co GL_FUN(BindFramebuffer, PFNGLBINDFRAMEBUFFERPROC) \ GL_FUN(FramebufferTexture2D, PFNGLFRAMEBUFFERTEXTURE2DPROC) \ GL_FUN(FramebufferRenderbuffer, PFNGLFRAMEBUFFERRENDERBUFFERPROC) \ - GL_FUN(BlitFramebuffer, PFNGLBLITFRAMEBUFFERPROC) \ - /* Renderbuffer object */ \ - GL_FUN(GenRenderbuffers, PFNGLGENRENDERBUFFERSPROC) \ - GL_FUN(DeleteRenderbuffers, PFNGLDELETERENDERBUFFERSPROC) \ - GL_FUN(BindRenderbuffer, PFNGLBINDRENDERBUFFERPROC) \ - GL_FUN(RenderbufferStorage, PFNGLRENDERBUFFERSTORAGEPROC) + GL_FUN(BlitFramebuffer, PFNGLBLITFRAMEBUFFERPROC) #define GL_VAO_FUN \ /* Vertex array object */ \ diff --git a/src/gl-meta.cpp b/src/gl-meta.cpp index 5f208ea..3330726 100644 --- a/src/gl-meta.cpp +++ b/src/gl-meta.cpp @@ -21,6 +21,9 @@ #include "gl-meta.h" #include "gl-fun.h" +#include "sharedstate.h" +#include "glstate.h" +#include "quad.h" namespace GLMeta { @@ -121,4 +124,81 @@ void vaoUnbind(VAO &vao) } } +#define HAVE_NATIVE_BLIT gl.BlitFramebuffer + +static void _blitBegin(FBO::ID fbo, const Vec2i &size) +{ + if (HAVE_NATIVE_BLIT) + { + FBO::bind(fbo, FBO::Draw); + } + else + { + FBO::bind(fbo, FBO::Generic); + glState.viewport.pushSet(IntRect(0, 0, size.x, size.y)); + + SimpleShader &shader = shState->shaders().simple; + shader.bind(); + shader.applyViewportProj(); + shader.setTranslation(Vec2i()); + } +} + +void blitBegin(TEXFBO &target) +{ + _blitBegin(target.fbo, Vec2i(target.width, target.height)); +} + +void blitBeginScreen(const Vec2i &size) +{ + _blitBegin(FBO::ID(0), size); +} + +void blitSource(TEXFBO &source) +{ + if (HAVE_NATIVE_BLIT) + { + FBO::bind(source.fbo, FBO::Read); + } + else + { + SimpleShader &shader = shState->shaders().simple; + shader.setTexSize(Vec2i(source.width, source.height)); + TEX::bind(source.tex); + } +} + +void blitRectangle(const IntRect &src, const Vec2i &dstPos, FBO::BlitMode mode) +{ + blitRectangle(src, IntRect(dstPos.x, dstPos.y, src.w, src.h), mode); +} + +void blitRectangle(const IntRect &src, const IntRect &dst, FBO::BlitMode mode) +{ + if (HAVE_NATIVE_BLIT) + { + FBO::blit(src.x, src.y, src.w, src.h, + dst.x, dst.y, dst.w, dst.h, + mode); + } + else + { + if (mode == FBO::Linear) + TEX::setSmooth(true); + + Quad &quad = shState->gpQuad(); + quad.setTexPosRect(src, dst); + quad.draw(); + + if (mode == FBO::Linear) + TEX::setSmooth(false); + } +} + +void blitFinish() +{ + if (!HAVE_NATIVE_BLIT) + glState.viewport.pop(); +} + } diff --git a/src/gl-meta.h b/src/gl-meta.h index 4dc585d..bfe1614 100644 --- a/src/gl-meta.h +++ b/src/gl-meta.h @@ -64,6 +64,16 @@ void vaoFini(VAO &vao); void vaoBind(VAO &vao); void vaoUnbind(VAO &vao); +/* EXT_framebuffer_blit */ +void blitBegin(TEXFBO &target); +void blitBeginScreen(const Vec2i &size); +void blitSource(TEXFBO &source); +void blitRectangle(const IntRect &src, const Vec2i &dstPos, + FBO::BlitMode mode = FBO::Nearest); +void blitRectangle(const IntRect &src, const IntRect &dst, + FBO::BlitMode mode = FBO::Nearest); +void blitFinish(); + } #endif // GLMETA_H diff --git a/src/gl-util.h b/src/gl-util.h index 68ace4a..c98f557 100644 --- a/src/gl-util.h +++ b/src/gl-util.h @@ -100,40 +100,6 @@ namespace TEX } } -/* Renderbuffer Object */ -namespace RBO -{ - DEF_GL_ID - - inline ID gen() - { - ID id; - gl.GenRenderbuffers(1, &id.gl); - - return id; - } - - inline void del(ID id) - { - gl.DeleteRenderbuffers(1, &id.gl); - } - - inline void bind(ID id) - { - gl.BindRenderbuffer(GL_RENDERBUFFER, id.gl); - } - - inline void unbind() - { - bind(ID(0)); - } - - inline void allocEmpty(GLsizei width, GLsizei height) - { - gl.RenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); - } -} - /* Framebuffer Object */ namespace FBO { @@ -142,7 +108,8 @@ namespace FBO enum Mode { Draw = 0, - Read = 1 + Read = 1, + Generic = 2 }; enum BlitMode @@ -169,7 +136,8 @@ namespace FBO static const GLenum modes[] = { GL_DRAW_FRAMEBUFFER, - GL_READ_FRAMEBUFFER + GL_READ_FRAMEBUFFER, + GL_FRAMEBUFFER }; gl.BindFramebuffer(modes[mode], id.gl); @@ -185,11 +153,6 @@ namespace FBO gl.FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttach, GL_TEXTURE_2D, target.gl, 0); } - inline void setTarget(RBO::ID target, unsigned colorAttach = 0) - { - gl.FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttach, GL_RENDERBUFFER, target.gl); - } - inline void blit(int srcX, int srcY, int srcW, int srcH, int dstX, int dstY, @@ -367,43 +330,4 @@ struct TEXFBO } }; -/* Convenience struct wrapping a framebuffer - * and a renderbuffer as its target */ -struct RBOFBO -{ - RBO::ID rbo; - FBO::ID fbo; - int width, height; - - RBOFBO() - : rbo(0), fbo(0), width(0), height(0) - {} - - static inline void init(RBOFBO &obj) - { - obj.rbo = RBO::gen(); - obj.fbo = FBO::gen(); - } - - static inline void allocEmpty(RBOFBO &obj, int width, int height) - { - RBO::bind(obj.rbo); - RBO::allocEmpty(width, height); - obj.width = width; - obj.height = height; - } - - static inline void linkFBO(RBOFBO &obj) - { - FBO::bind(obj.fbo, FBO::Draw); - FBO::setTarget(obj.rbo); - } - - static inline void fini(RBOFBO &obj) - { - FBO::del(obj.fbo); - RBO::del(obj.rbo); - } -}; - #endif // GLUTIL_H diff --git a/src/graphics.cpp b/src/graphics.cpp index b27cd57..b781245 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -70,10 +70,14 @@ struct PingPong TEXFBO::fini(rt[i]); } - /* Binds FBO of last good buffer for reading */ - void bindLastBuffer() + TEXFBO &backBuffer() { - FBO::bind(rt[dstInd].fbo, FBO::Read); + return rt[srcInd]; + } + + TEXFBO &frontBuffer() + { + return rt[dstInd]; } /* Better not call this during render cycles */ @@ -100,23 +104,10 @@ struct PingPong bind(); } - void blitFBOs() - { - FBO::blit(0, 0, 0, 0, screenW, screenH); - } - - void finishRender() - { - FBO::unbind(FBO::Draw); - FBO::bind(rt[dstInd].fbo, FBO::Read); - } - private: void bind() { - TEX::bind(rt[srcInd].tex); - FBO::bind(rt[srcInd].fbo, FBO::Read); - FBO::bind(rt[dstInd].fbo, FBO::Draw); + FBO::bind(rt[dstInd].fbo, FBO::Generic); } }; @@ -160,8 +151,6 @@ public: brightnessQuad.draw(); } #endif - - pp.finishRender(); } void requestViewportRender(Vec4 &c, Vec4 &f, Vec4 &t) @@ -172,7 +161,12 @@ public: * and since we're inside the draw cycle, it will * be turned on, so turn it off temporarily */ glState.scissorTest.pushSet(false); - pp.blitFBOs(); + + GLMeta::blitBegin(pp.frontBuffer()); + GLMeta::blitSetSource(pp.backBuffer()); + GLMeta::blitRectangle(geometry.rect, Vec2i()); + GLMeta::blitFinish(); + glState.scissorTest.pop(); PlaneShader &shader = shState->shaders().plane; @@ -184,6 +178,8 @@ public: shader.applyViewportProj(); shader.setTexSize(geometry.rect.size()); + TEX::bind(pp.backBuffer().tex); + glState.blendMode.pushSet(BlendNone); screenQuad.draw(); @@ -399,7 +395,7 @@ struct GraphicsPrivate TEXFBO frozenScene; TEXFBO currentScene; Quad screenQuad; - RBOFBO transBuffer; + TEXFBO transBuffer; GraphicsPrivate(RGSSThreadData *rtData) : scRes(640, 480), @@ -429,9 +425,9 @@ struct GraphicsPrivate FloatRect screenRect(0, 0, scRes.x, scRes.y); screenQuad.setTexPosRect(screenRect, screenRect); - RBOFBO::init(transBuffer); - RBOFBO::allocEmpty(transBuffer, scRes.x, scRes.y); - RBOFBO::linkFBO(transBuffer); + TEXFBO::init(transBuffer); + TEXFBO::allocEmpty(transBuffer, scRes.x, scRes.y); + TEXFBO::linkFBO(transBuffer); } ~GraphicsPrivate() @@ -439,7 +435,7 @@ struct GraphicsPrivate TEXFBO::fini(frozenScene); TEXFBO::fini(currentScene); - RBOFBO::fini(transBuffer); + TEXFBO::fini(transBuffer); } void updateScreenResoRatio(RGSSThreadData *rtData) @@ -503,25 +499,34 @@ struct GraphicsPrivate threadData->ethread->notifyFrame(); } - void compositeToBuffer(FBO::ID fbo) + void compositeToBuffer(TEXFBO &buffer) { screen.composite(); - FBO::bind(fbo, FBO::Draw); - FBO::blit(0, 0, 0, 0, scRes.x, scRes.y); + + GLMeta::blitBegin(buffer); + GLMeta::blitSetSource(screen.getPP().frontBuffer()); + GLMeta::blitRectangle(IntRect(0, 0, scRes.x, scRes.y), Vec2i()); + GLMeta::blitFinish(); } - void blitBufferFlippedScaled() + void metaBlitBufferFlippedScaled() { - FBO::blit(0, 0, scRes.x, scRes.y, - scOffset.x, scSize.y+scOffset.y, scSize.x, -scSize.y, - threadData->config.smoothScaling ? FBO::Linear : FBO::Nearest); + GLMeta::blitRectangle(IntRect(0, 0, scRes.x, scRes.y), + IntRect(scOffset.x, scSize.y+scOffset.y, scSize.x, -scSize.y), + threadData->config.smoothScaling ? FBO::Linear : FBO::Nearest); } void redrawScreen() { screen.composite(); + + GLMeta::blitBeginScreen(winSize); + GLMeta::blitSetSource(screen.getPP().frontBuffer()); + FBO::clear(); - blitBufferFlippedScaled(); + metaBlitBufferFlippedScaled(); + + GLMeta::blitFinish(); swapGLBuffer(); } @@ -579,7 +584,7 @@ void Graphics::freeze() p->checkResize(); /* Capture scene into frozen buffer */ - p->compositeToBuffer(p->frozenScene.fbo); + p->compositeToBuffer(p->frozenScene); } void Graphics::transition(int duration, @@ -594,13 +599,16 @@ void Graphics::transition(int duration, #endif /* Capture new scene */ - p->compositeToBuffer(p->currentScene.fbo); + p->compositeToBuffer(p->currentScene); /* If no transition bitmap is provided, * we can use a simplified shader */ + TransShader &transShader = shState->shaders().trans; + SimpleTransShader &simpleShader = shState->shaders().simpleTrans; + if (transMap) { - TransShader &shader = shState->shaders().trans; + TransShader &shader = transShader; shader.bind(); shader.applyViewportProj(); shader.setFrozenScene(p->frozenScene.tex); @@ -611,7 +619,7 @@ void Graphics::transition(int duration, } else { - SimpleTransShader &shader = shState->shaders().simpleTrans; + SimpleTransShader &shader = simpleShader; shader.bind(); shader.applyViewportProj(); shader.setFrozenScene(p->frozenScene.tex); @@ -632,23 +640,32 @@ void Graphics::transition(int duration, const float prog = i * (1.0 / duration); if (transMap) - shState->shaders().trans.setProg(prog); + { + transShader.bind(); + transShader.setProg(prog); + } else - shState->shaders().simpleTrans.setProg(prog); + { + simpleShader.bind(); + simpleShader.setProg(prog); + } /* Draw the composed frame to a buffer first * (we need this because we're skipping PingPong) */ - FBO::bind(p->transBuffer.fbo, FBO::Draw); + FBO::bind(p->transBuffer.fbo, FBO::Generic); FBO::clear(); p->screenQuad.draw(); p->checkResize(); /* Then blit it flipped and scaled to the screen */ - FBO::bind(p->transBuffer.fbo, FBO::Read); - FBO::unbind(FBO::Draw); + FBO::unbind(FBO::Generic); FBO::clear(); - p->blitBufferFlippedScaled(); + + GLMeta::blitBeginScreen(Vec2i(p->winSize)); + GLMeta::blitSetSource(p->transBuffer); + p->metaBlitBufferFlippedScaled(); + GLMeta::blitFinish(); p->swapGLBuffer(); } @@ -699,10 +716,7 @@ void Graphics::wait(int duration) void Graphics::fadeout(int duration) { - if (p->frozen) - FBO::bind(p->frozenScene.fbo, FBO::Read); - - FBO::unbind(FBO::Draw); + FBO::unbind(FBO::Generic); for (int i = duration-1; i > -1; --i) { @@ -710,8 +724,14 @@ void Graphics::fadeout(int duration) if (p->frozen) { + GLMeta::blitBeginScreen(p->scSize); + GLMeta::blitSetSource(p->frozenScene); + FBO::clear(); - p->blitBufferFlippedScaled(); + p->metaBlitBufferFlippedScaled(); + + GLMeta::blitFinish(); + p->swapGLBuffer(); } else @@ -723,10 +743,7 @@ void Graphics::fadeout(int duration) void Graphics::fadein(int duration) { - if (p->frozen) - FBO::bind(p->frozenScene.fbo, FBO::Read); - - FBO::unbind(FBO::Draw); + FBO::unbind(FBO::Generic); for (int i = 0; i < duration; ++i) { @@ -734,8 +751,14 @@ void Graphics::fadein(int duration) if (p->frozen) { + GLMeta::blitBeginScreen(p->scSize); + GLMeta::blitSetSource(p->frozenScene); + FBO::clear(); - p->blitBufferFlippedScaled(); + p->metaBlitBufferFlippedScaled(); + + GLMeta::blitFinish(); + p->swapGLBuffer(); } else @@ -749,7 +772,7 @@ Bitmap *Graphics::snapToBitmap() { Bitmap *bitmap = new Bitmap(width(), height()); - p->compositeToBuffer(bitmap->getGLTypes().fbo); + p->compositeToBuffer(bitmap->getGLTypes()); /* Taint entire bitmap */ bitmap->taintArea(IntRect(0, 0, width(), height())); @@ -791,8 +814,8 @@ void Graphics::resizeScreen(int width, int height) FloatRect screenRect(0, 0, width, height); p->screenQuad.setTexPosRect(screenRect, screenRect); - RBO::bind(p->transBuffer.rbo); - RBO::allocEmpty(width, height); + TEX::bind(p->transBuffer.tex); + TEX::allocEmpty(width, height); p->updateScreenResoRatio(p->threadData); } @@ -843,18 +866,21 @@ void Graphics::repaintWait(volatile bool *exitCond) return; /* Repaint the screen with the last good frame we drew */ - p->screen.getPP().bindLastBuffer(); - FBO::unbind(FBO::Draw); + TEXFBO &lastFrame = p->screen.getPP().frontBuffer(); + GLMeta::blitBeginScreen(p->winSize); + GLMeta::blitSetSource(lastFrame); while (!*exitCond) { shState->checkShutdown(); FBO::clear(); - p->blitBufferFlippedScaled(); + p->metaBlitBufferFlippedScaled(); SDL_GL_SwapWindow(p->threadData->window); p->fpsLimiter.delay(); p->threadData->ethread->notifyFrame(); } + + GLMeta::blitFinish(); } diff --git a/src/shader.cpp b/src/shader.cpp index 659b536..2292780 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -294,17 +294,17 @@ TransShader::TransShader() void TransShader::setCurrentScene(TEX::ID tex) { - setTexUniform(u_currentScene, 0, tex); + setTexUniform(u_currentScene, 1, tex); } void TransShader::setFrozenScene(TEX::ID tex) { - setTexUniform(u_frozenScene, 1, tex); + setTexUniform(u_frozenScene, 2, tex); } void TransShader::setTransMap(TEX::ID tex) { - setTexUniform(u_transMap, 2, tex); + setTexUniform(u_transMap, 3, tex); } void TransShader::setProg(float value) @@ -331,12 +331,12 @@ SimpleTransShader::SimpleTransShader() void SimpleTransShader::setCurrentScene(TEX::ID tex) { - setTexUniform(u_currentScene, 0, tex); + setTexUniform(u_currentScene, 1, tex); } void SimpleTransShader::setFrozenScene(TEX::ID tex) { - setTexUniform(u_frozenScene, 1, tex); + setTexUniform(u_frozenScene, 2, tex); } void SimpleTransShader::setProg(float value) diff --git a/src/tilemap.cpp b/src/tilemap.cpp index cc5e0a6..58b0679 100644 --- a/src/tilemap.cpp +++ b/src/tilemap.cpp @@ -551,7 +551,7 @@ struct TilemapPrivate TileAtlas::BlitVec blits = TileAtlas::calcBlits(atlas.efTilesetH, atlas.size); /* Clear atlas */ - FBO::bind(atlas.gl.fbo, FBO::Draw); + FBO::bind(atlas.gl.fbo, FBO::Generic); glState.clearColor.pushSet(Vec4()); glState.scissorTest.pushSet(false); @@ -560,6 +560,8 @@ struct TilemapPrivate glState.scissorTest.pop(); glState.clearColor.pop(); + GLMeta::blitBegin(atlas.gl); + /* Blit autotiles */ for (size_t i = 0; i < atlas.usableATs.size(); ++i) { @@ -569,26 +571,29 @@ struct TilemapPrivate int blitW = std::min(autotile->width(), atAreaW); int blitH = std::min(autotile->height(), atAreaH); - FBO::bind(autotile->getGLTypes().fbo, FBO::Read); + GLMeta::blitSource(autotile->getGLTypes()); if (blitW <= autotileW && tiles.animated) { /* Static autotile */ for (int j = 0; j < 4; ++j) - FBO::blit(0, 0, autotileW*j, atInd*autotileH, blitW, blitH); + GLMeta::blitRectangle(IntRect(0, 0, blitW, blitH), + Vec2i(autotileW*j, atInd*autotileH)); } else { /* Animated autotile */ - FBO::blit(0, 0, 0, atInd*autotileH, blitW, blitH); + GLMeta::blitRectangle(IntRect(0, 0, blitW, blitH), + Vec2i(0, atInd*autotileH)); } } + GLMeta::blitFinish(); + /* Blit tileset */ if (tileset->megaSurface()) { /* Mega surface tileset */ - FBO::unbind(FBO::Draw); TEX::bind(atlas.gl.tex); SDL_Surface *tsSurf = tileset->megaSurface(); @@ -606,14 +611,18 @@ struct TilemapPrivate else { /* Regular tileset */ - FBO::bind(tileset->getGLTypes().fbo, FBO::Read); + GLMeta::blitBegin(atlas.gl); + GLMeta::blitSource(tileset->getGLTypes()); for (size_t i = 0; i < blits.size(); ++i) { const TileAtlas::Blit &blitOp = blits[i]; - FBO::blit(blitOp.src.x, blitOp.src.y, blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h); + GLMeta::blitRectangle(IntRect(blitOp.src.x, blitOp.src.y, tsLaneW, blitOp.h), + blitOp.dst); } + + GLMeta::blitFinish(); } } diff --git a/src/window.cpp b/src/window.cpp index 3cc952d..0a29518 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -416,7 +416,7 @@ struct WindowPrivate TEX::allocEmpty(baseTex.width, baseTex.height); TEX::unbind(); - FBO::bind(baseTex.fbo, FBO::Draw); + FBO::bind(baseTex.fbo, FBO::Generic); glState.viewport.pushSet(IntRect(0, 0, baseTex.width, baseTex.height)); glState.clearColor.pushSet(Vec4());