GLMeta: Add framebuffer blitting support

This commit is contained in:
Jonas Kulla 2014-07-16 04:48:40 +02:00
parent 7ad6b7b5df
commit a26c73930d
9 changed files with 225 additions and 181 deletions

View File

@ -150,7 +150,7 @@ struct BitmapPrivate
void bindFBO() void bindFBO()
{ {
FBO::bind(gl.fbo, FBO::Draw); FBO::bind(gl.fbo, FBO::Generic);
} }
void pushSetViewport(ShaderBase &shader) const void pushSetViewport(ShaderBase &shader) const
@ -384,11 +384,10 @@ void Bitmap::stretchBlt(const IntRect &destRect,
if (opacity == 255 && !p->touchesTaintedArea(destRect)) if (opacity == 255 && !p->touchesTaintedArea(destRect))
{ {
/* Fast blit */ /* Fast blit */
FBO::bind(source.p->gl.fbo, FBO::Read); GLMeta::blitBegin(p->gl);
FBO::bind(p->gl.fbo, FBO::Draw); GLMeta::blitSource(source.p->gl);
GLMeta::blitRectangle(sourceRect, destRect);
FBO::blit(sourceRect.x, sourceRect.y, sourceRect.w, sourceRect.h, GLMeta::blitFinish();
destRect.x, destRect.y, destRect.w, destRect.h);
} }
else else
{ {
@ -397,9 +396,10 @@ void Bitmap::stretchBlt(const IntRect &destRect,
TEXFBO &gpTex = shState->gpTexFBO(destRect.w, destRect.h); TEXFBO &gpTex = shState->gpTexFBO(destRect.w, destRect.h);
FBO::bind(gpTex.fbo, FBO::Draw); GLMeta::blitBegin(gpTex);
FBO::bind(p->gl.fbo, FBO::Read); GLMeta::blitSource(p->gl);
FBO::blit(destRect.x, destRect.y, 0, 0, destRect.w, destRect.h); GLMeta::blitRectangle(destRect, Vec2i());
GLMeta::blitFinish();
FloatRect bltSubRect((float) sourceRect.x / source.width(), FloatRect bltSubRect((float) sourceRect.x / source.width(),
(float) sourceRect.y / source.height(), (float) sourceRect.y / source.height(),
@ -544,7 +544,7 @@ void Bitmap::blur()
glState.viewport.pushSet(IntRect(0, 0, width(), height())); glState.viewport.pushSet(IntRect(0, 0, width(), height()));
TEX::bind(p->gl.tex); TEX::bind(p->gl.tex);
FBO::bind(auxTex.fbo, FBO::Draw); FBO::bind(auxTex.fbo, FBO::Generic);
pass1.bind(); pass1.bind();
pass1.setTexSize(Vec2i(width(), height())); pass1.setTexSize(Vec2i(width(), height()));
@ -553,7 +553,7 @@ void Bitmap::blur()
quad.draw(); quad.draw();
TEX::bind(auxTex.tex); TEX::bind(auxTex.tex);
FBO::bind(p->gl.fbo, FBO::Draw); p->bindFBO();
pass2.bind(); pass2.bind();
pass2.setTexSize(Vec2i(width(), height())); pass2.setTexSize(Vec2i(width(), height()));
@ -625,7 +625,7 @@ void Bitmap::radialBlur(int angle, int divisions)
TEXFBO newTex = shState->texPool().request(_width, _height); TEXFBO newTex = shState->texPool().request(_width, _height);
FBO::bind(newTex.fbo, FBO::Draw); FBO::bind(newTex.fbo, FBO::Generic);
glState.clearColor.pushSet(Vec4()); glState.clearColor.pushSet(Vec4());
FBO::clear(); FBO::clear();
@ -698,7 +698,7 @@ Color Bitmap::getPixel(int x, int y) const
{ {
p->allocSurface(); p->allocSurface();
FBO::bind(p->gl.fbo, FBO::Read); FBO::bind(p->gl.fbo, FBO::Generic);
glState.viewport.pushSet(IntRect(0, 0, width(), height())); glState.viewport.pushSet(IntRect(0, 0, width(), height()));
@ -764,7 +764,7 @@ void Bitmap::hueChange(int hue)
shader.bind(); shader.bind();
shader.setHueAdjust(hueAdj); shader.setHueAdjust(hueAdj);
FBO::bind(newTex.fbo, FBO::Draw); FBO::bind(newTex.fbo, FBO::Generic);
p->pushSetViewport(shader); p->pushSetViewport(shader);
p->bindTexture(shader); p->bindTexture(shader);
@ -918,12 +918,11 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
TEX::bind(gpTF.tex); TEX::bind(gpTF.tex);
TEX::uploadSubImage(0, 0, txtSurf->w, txtSurf->h, txtSurf->pixels, GL_BGRA); TEX::uploadSubImage(0, 0, txtSurf->w, txtSurf->h, txtSurf->pixels, GL_BGRA);
FBO::bind(gpTF.fbo, FBO::Read); GLMeta::blitBegin(p->gl);
p->bindFBO(); GLMeta::blitSource(gpTF);
GLMeta::blitRectangle(IntRect(0, 0, txtSurf->w, txtSurf->h),
FBO::blit(0, 0, txtSurf->w, txtSurf->h, posRect, FBO::Linear);
posRect.x, posRect.y, posRect.w, posRect.h, GLMeta::blitFinish();
FBO::Linear);
} }
} }
else else
@ -932,9 +931,10 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
* buffer we're about to render to */ * buffer we're about to render to */
TEXFBO &gpTex2 = shState->gpTexFBO(posRect.w, posRect.h); TEXFBO &gpTex2 = shState->gpTexFBO(posRect.w, posRect.h);
FBO::bind(gpTex2.fbo, FBO::Draw); GLMeta::blitBegin(gpTex2);
FBO::bind(p->gl.fbo, FBO::Read); GLMeta::blitSource(p->gl);
FBO::blit(posRect.x, posRect.y, 0, 0, posRect.w, posRect.h); GLMeta::blitRectangle(posRect, Vec2i());
GLMeta::blitFinish();
FloatRect bltRect(0, 0, FloatRect bltRect(0, 0,
(float) gpTexSize.x / gpTex2.width, (float) gpTexSize.x / gpTex2.width,

View File

@ -120,12 +120,7 @@ typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, co
GL_FUN(BindFramebuffer, PFNGLBINDFRAMEBUFFERPROC) \ GL_FUN(BindFramebuffer, PFNGLBINDFRAMEBUFFERPROC) \
GL_FUN(FramebufferTexture2D, PFNGLFRAMEBUFFERTEXTURE2DPROC) \ GL_FUN(FramebufferTexture2D, PFNGLFRAMEBUFFERTEXTURE2DPROC) \
GL_FUN(FramebufferRenderbuffer, PFNGLFRAMEBUFFERRENDERBUFFERPROC) \ GL_FUN(FramebufferRenderbuffer, PFNGLFRAMEBUFFERRENDERBUFFERPROC) \
GL_FUN(BlitFramebuffer, PFNGLBLITFRAMEBUFFERPROC) \ GL_FUN(BlitFramebuffer, PFNGLBLITFRAMEBUFFERPROC)
/* Renderbuffer object */ \
GL_FUN(GenRenderbuffers, PFNGLGENRENDERBUFFERSPROC) \
GL_FUN(DeleteRenderbuffers, PFNGLDELETERENDERBUFFERSPROC) \
GL_FUN(BindRenderbuffer, PFNGLBINDRENDERBUFFERPROC) \
GL_FUN(RenderbufferStorage, PFNGLRENDERBUFFERSTORAGEPROC)
#define GL_VAO_FUN \ #define GL_VAO_FUN \
/* Vertex array object */ \ /* Vertex array object */ \

View File

@ -21,6 +21,9 @@
#include "gl-meta.h" #include "gl-meta.h"
#include "gl-fun.h" #include "gl-fun.h"
#include "sharedstate.h"
#include "glstate.h"
#include "quad.h"
namespace GLMeta 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();
}
} }

View File

@ -64,6 +64,16 @@ void vaoFini(VAO &vao);
void vaoBind(VAO &vao); void vaoBind(VAO &vao);
void vaoUnbind(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 #endif // GLMETA_H

View File

@ -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 */ /* Framebuffer Object */
namespace FBO namespace FBO
{ {
@ -142,7 +108,8 @@ namespace FBO
enum Mode enum Mode
{ {
Draw = 0, Draw = 0,
Read = 1 Read = 1,
Generic = 2
}; };
enum BlitMode enum BlitMode
@ -169,7 +136,8 @@ namespace FBO
static const GLenum modes[] = static const GLenum modes[] =
{ {
GL_DRAW_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER,
GL_READ_FRAMEBUFFER GL_READ_FRAMEBUFFER,
GL_FRAMEBUFFER
}; };
gl.BindFramebuffer(modes[mode], id.gl); 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); 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, inline void blit(int srcX, int srcY,
int srcW, int srcH, int srcW, int srcH,
int dstX, int dstY, 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 #endif // GLUTIL_H

View File

@ -70,10 +70,14 @@ struct PingPong
TEXFBO::fini(rt[i]); TEXFBO::fini(rt[i]);
} }
/* Binds FBO of last good buffer for reading */ TEXFBO &backBuffer()
void bindLastBuffer()
{ {
FBO::bind(rt[dstInd].fbo, FBO::Read); return rt[srcInd];
}
TEXFBO &frontBuffer()
{
return rt[dstInd];
} }
/* Better not call this during render cycles */ /* Better not call this during render cycles */
@ -100,23 +104,10 @@ struct PingPong
bind(); 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: private:
void bind() void bind()
{ {
TEX::bind(rt[srcInd].tex); FBO::bind(rt[dstInd].fbo, FBO::Generic);
FBO::bind(rt[srcInd].fbo, FBO::Read);
FBO::bind(rt[dstInd].fbo, FBO::Draw);
} }
}; };
@ -160,8 +151,6 @@ public:
brightnessQuad.draw(); brightnessQuad.draw();
} }
#endif #endif
pp.finishRender();
} }
void requestViewportRender(Vec4 &c, Vec4 &f, Vec4 &t) void requestViewportRender(Vec4 &c, Vec4 &f, Vec4 &t)
@ -172,7 +161,12 @@ public:
* and since we're inside the draw cycle, it will * and since we're inside the draw cycle, it will
* be turned on, so turn it off temporarily */ * be turned on, so turn it off temporarily */
glState.scissorTest.pushSet(false); glState.scissorTest.pushSet(false);
pp.blitFBOs();
GLMeta::blitBegin(pp.frontBuffer());
GLMeta::blitSetSource(pp.backBuffer());
GLMeta::blitRectangle(geometry.rect, Vec2i());
GLMeta::blitFinish();
glState.scissorTest.pop(); glState.scissorTest.pop();
PlaneShader &shader = shState->shaders().plane; PlaneShader &shader = shState->shaders().plane;
@ -184,6 +178,8 @@ public:
shader.applyViewportProj(); shader.applyViewportProj();
shader.setTexSize(geometry.rect.size()); shader.setTexSize(geometry.rect.size());
TEX::bind(pp.backBuffer().tex);
glState.blendMode.pushSet(BlendNone); glState.blendMode.pushSet(BlendNone);
screenQuad.draw(); screenQuad.draw();
@ -399,7 +395,7 @@ struct GraphicsPrivate
TEXFBO frozenScene; TEXFBO frozenScene;
TEXFBO currentScene; TEXFBO currentScene;
Quad screenQuad; Quad screenQuad;
RBOFBO transBuffer; TEXFBO transBuffer;
GraphicsPrivate(RGSSThreadData *rtData) GraphicsPrivate(RGSSThreadData *rtData)
: scRes(640, 480), : scRes(640, 480),
@ -429,9 +425,9 @@ struct GraphicsPrivate
FloatRect screenRect(0, 0, scRes.x, scRes.y); FloatRect screenRect(0, 0, scRes.x, scRes.y);
screenQuad.setTexPosRect(screenRect, screenRect); screenQuad.setTexPosRect(screenRect, screenRect);
RBOFBO::init(transBuffer); TEXFBO::init(transBuffer);
RBOFBO::allocEmpty(transBuffer, scRes.x, scRes.y); TEXFBO::allocEmpty(transBuffer, scRes.x, scRes.y);
RBOFBO::linkFBO(transBuffer); TEXFBO::linkFBO(transBuffer);
} }
~GraphicsPrivate() ~GraphicsPrivate()
@ -439,7 +435,7 @@ struct GraphicsPrivate
TEXFBO::fini(frozenScene); TEXFBO::fini(frozenScene);
TEXFBO::fini(currentScene); TEXFBO::fini(currentScene);
RBOFBO::fini(transBuffer); TEXFBO::fini(transBuffer);
} }
void updateScreenResoRatio(RGSSThreadData *rtData) void updateScreenResoRatio(RGSSThreadData *rtData)
@ -503,25 +499,34 @@ struct GraphicsPrivate
threadData->ethread->notifyFrame(); threadData->ethread->notifyFrame();
} }
void compositeToBuffer(FBO::ID fbo) void compositeToBuffer(TEXFBO &buffer)
{ {
screen.composite(); 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, GLMeta::blitRectangle(IntRect(0, 0, scRes.x, scRes.y),
scOffset.x, scSize.y+scOffset.y, scSize.x, -scSize.y, IntRect(scOffset.x, scSize.y+scOffset.y, scSize.x, -scSize.y),
threadData->config.smoothScaling ? FBO::Linear : FBO::Nearest); threadData->config.smoothScaling ? FBO::Linear : FBO::Nearest);
} }
void redrawScreen() void redrawScreen()
{ {
screen.composite(); screen.composite();
GLMeta::blitBeginScreen(winSize);
GLMeta::blitSetSource(screen.getPP().frontBuffer());
FBO::clear(); FBO::clear();
blitBufferFlippedScaled(); metaBlitBufferFlippedScaled();
GLMeta::blitFinish();
swapGLBuffer(); swapGLBuffer();
} }
@ -579,7 +584,7 @@ void Graphics::freeze()
p->checkResize(); p->checkResize();
/* Capture scene into frozen buffer */ /* Capture scene into frozen buffer */
p->compositeToBuffer(p->frozenScene.fbo); p->compositeToBuffer(p->frozenScene);
} }
void Graphics::transition(int duration, void Graphics::transition(int duration,
@ -594,13 +599,16 @@ void Graphics::transition(int duration,
#endif #endif
/* Capture new scene */ /* Capture new scene */
p->compositeToBuffer(p->currentScene.fbo); p->compositeToBuffer(p->currentScene);
/* If no transition bitmap is provided, /* If no transition bitmap is provided,
* we can use a simplified shader */ * we can use a simplified shader */
TransShader &transShader = shState->shaders().trans;
SimpleTransShader &simpleShader = shState->shaders().simpleTrans;
if (transMap) if (transMap)
{ {
TransShader &shader = shState->shaders().trans; TransShader &shader = transShader;
shader.bind(); shader.bind();
shader.applyViewportProj(); shader.applyViewportProj();
shader.setFrozenScene(p->frozenScene.tex); shader.setFrozenScene(p->frozenScene.tex);
@ -611,7 +619,7 @@ void Graphics::transition(int duration,
} }
else else
{ {
SimpleTransShader &shader = shState->shaders().simpleTrans; SimpleTransShader &shader = simpleShader;
shader.bind(); shader.bind();
shader.applyViewportProj(); shader.applyViewportProj();
shader.setFrozenScene(p->frozenScene.tex); shader.setFrozenScene(p->frozenScene.tex);
@ -632,23 +640,32 @@ void Graphics::transition(int duration,
const float prog = i * (1.0 / duration); const float prog = i * (1.0 / duration);
if (transMap) if (transMap)
shState->shaders().trans.setProg(prog); {
transShader.bind();
transShader.setProg(prog);
}
else else
shState->shaders().simpleTrans.setProg(prog); {
simpleShader.bind();
simpleShader.setProg(prog);
}
/* Draw the composed frame to a buffer first /* Draw the composed frame to a buffer first
* (we need this because we're skipping PingPong) */ * (we need this because we're skipping PingPong) */
FBO::bind(p->transBuffer.fbo, FBO::Draw); FBO::bind(p->transBuffer.fbo, FBO::Generic);
FBO::clear(); FBO::clear();
p->screenQuad.draw(); p->screenQuad.draw();
p->checkResize(); p->checkResize();
/* Then blit it flipped and scaled to the screen */ /* Then blit it flipped and scaled to the screen */
FBO::bind(p->transBuffer.fbo, FBO::Read); FBO::unbind(FBO::Generic);
FBO::unbind(FBO::Draw);
FBO::clear(); FBO::clear();
p->blitBufferFlippedScaled();
GLMeta::blitBeginScreen(Vec2i(p->winSize));
GLMeta::blitSetSource(p->transBuffer);
p->metaBlitBufferFlippedScaled();
GLMeta::blitFinish();
p->swapGLBuffer(); p->swapGLBuffer();
} }
@ -699,10 +716,7 @@ void Graphics::wait(int duration)
void Graphics::fadeout(int duration) void Graphics::fadeout(int duration)
{ {
if (p->frozen) FBO::unbind(FBO::Generic);
FBO::bind(p->frozenScene.fbo, FBO::Read);
FBO::unbind(FBO::Draw);
for (int i = duration-1; i > -1; --i) for (int i = duration-1; i > -1; --i)
{ {
@ -710,8 +724,14 @@ void Graphics::fadeout(int duration)
if (p->frozen) if (p->frozen)
{ {
GLMeta::blitBeginScreen(p->scSize);
GLMeta::blitSetSource(p->frozenScene);
FBO::clear(); FBO::clear();
p->blitBufferFlippedScaled(); p->metaBlitBufferFlippedScaled();
GLMeta::blitFinish();
p->swapGLBuffer(); p->swapGLBuffer();
} }
else else
@ -723,10 +743,7 @@ void Graphics::fadeout(int duration)
void Graphics::fadein(int duration) void Graphics::fadein(int duration)
{ {
if (p->frozen) FBO::unbind(FBO::Generic);
FBO::bind(p->frozenScene.fbo, FBO::Read);
FBO::unbind(FBO::Draw);
for (int i = 0; i < duration; ++i) for (int i = 0; i < duration; ++i)
{ {
@ -734,8 +751,14 @@ void Graphics::fadein(int duration)
if (p->frozen) if (p->frozen)
{ {
GLMeta::blitBeginScreen(p->scSize);
GLMeta::blitSetSource(p->frozenScene);
FBO::clear(); FBO::clear();
p->blitBufferFlippedScaled(); p->metaBlitBufferFlippedScaled();
GLMeta::blitFinish();
p->swapGLBuffer(); p->swapGLBuffer();
} }
else else
@ -749,7 +772,7 @@ Bitmap *Graphics::snapToBitmap()
{ {
Bitmap *bitmap = new Bitmap(width(), height()); Bitmap *bitmap = new Bitmap(width(), height());
p->compositeToBuffer(bitmap->getGLTypes().fbo); p->compositeToBuffer(bitmap->getGLTypes());
/* Taint entire bitmap */ /* Taint entire bitmap */
bitmap->taintArea(IntRect(0, 0, width(), height())); bitmap->taintArea(IntRect(0, 0, width(), height()));
@ -791,8 +814,8 @@ void Graphics::resizeScreen(int width, int height)
FloatRect screenRect(0, 0, width, height); FloatRect screenRect(0, 0, width, height);
p->screenQuad.setTexPosRect(screenRect, screenRect); p->screenQuad.setTexPosRect(screenRect, screenRect);
RBO::bind(p->transBuffer.rbo); TEX::bind(p->transBuffer.tex);
RBO::allocEmpty(width, height); TEX::allocEmpty(width, height);
p->updateScreenResoRatio(p->threadData); p->updateScreenResoRatio(p->threadData);
} }
@ -843,18 +866,21 @@ void Graphics::repaintWait(volatile bool *exitCond)
return; return;
/* Repaint the screen with the last good frame we drew */ /* Repaint the screen with the last good frame we drew */
p->screen.getPP().bindLastBuffer(); TEXFBO &lastFrame = p->screen.getPP().frontBuffer();
FBO::unbind(FBO::Draw); GLMeta::blitBeginScreen(p->winSize);
GLMeta::blitSetSource(lastFrame);
while (!*exitCond) while (!*exitCond)
{ {
shState->checkShutdown(); shState->checkShutdown();
FBO::clear(); FBO::clear();
p->blitBufferFlippedScaled(); p->metaBlitBufferFlippedScaled();
SDL_GL_SwapWindow(p->threadData->window); SDL_GL_SwapWindow(p->threadData->window);
p->fpsLimiter.delay(); p->fpsLimiter.delay();
p->threadData->ethread->notifyFrame(); p->threadData->ethread->notifyFrame();
} }
GLMeta::blitFinish();
} }

View File

@ -294,17 +294,17 @@ TransShader::TransShader()
void TransShader::setCurrentScene(TEX::ID tex) void TransShader::setCurrentScene(TEX::ID tex)
{ {
setTexUniform(u_currentScene, 0, tex); setTexUniform(u_currentScene, 1, tex);
} }
void TransShader::setFrozenScene(TEX::ID tex) void TransShader::setFrozenScene(TEX::ID tex)
{ {
setTexUniform(u_frozenScene, 1, tex); setTexUniform(u_frozenScene, 2, tex);
} }
void TransShader::setTransMap(TEX::ID tex) void TransShader::setTransMap(TEX::ID tex)
{ {
setTexUniform(u_transMap, 2, tex); setTexUniform(u_transMap, 3, tex);
} }
void TransShader::setProg(float value) void TransShader::setProg(float value)
@ -331,12 +331,12 @@ SimpleTransShader::SimpleTransShader()
void SimpleTransShader::setCurrentScene(TEX::ID tex) void SimpleTransShader::setCurrentScene(TEX::ID tex)
{ {
setTexUniform(u_currentScene, 0, tex); setTexUniform(u_currentScene, 1, tex);
} }
void SimpleTransShader::setFrozenScene(TEX::ID tex) void SimpleTransShader::setFrozenScene(TEX::ID tex)
{ {
setTexUniform(u_frozenScene, 1, tex); setTexUniform(u_frozenScene, 2, tex);
} }
void SimpleTransShader::setProg(float value) void SimpleTransShader::setProg(float value)

View File

@ -551,7 +551,7 @@ struct TilemapPrivate
TileAtlas::BlitVec blits = TileAtlas::calcBlits(atlas.efTilesetH, atlas.size); TileAtlas::BlitVec blits = TileAtlas::calcBlits(atlas.efTilesetH, atlas.size);
/* Clear atlas */ /* Clear atlas */
FBO::bind(atlas.gl.fbo, FBO::Draw); FBO::bind(atlas.gl.fbo, FBO::Generic);
glState.clearColor.pushSet(Vec4()); glState.clearColor.pushSet(Vec4());
glState.scissorTest.pushSet(false); glState.scissorTest.pushSet(false);
@ -560,6 +560,8 @@ struct TilemapPrivate
glState.scissorTest.pop(); glState.scissorTest.pop();
glState.clearColor.pop(); glState.clearColor.pop();
GLMeta::blitBegin(atlas.gl);
/* Blit autotiles */ /* Blit autotiles */
for (size_t i = 0; i < atlas.usableATs.size(); ++i) for (size_t i = 0; i < atlas.usableATs.size(); ++i)
{ {
@ -569,26 +571,29 @@ struct TilemapPrivate
int blitW = std::min(autotile->width(), atAreaW); int blitW = std::min(autotile->width(), atAreaW);
int blitH = std::min(autotile->height(), atAreaH); int blitH = std::min(autotile->height(), atAreaH);
FBO::bind(autotile->getGLTypes().fbo, FBO::Read); GLMeta::blitSource(autotile->getGLTypes());
if (blitW <= autotileW && tiles.animated) if (blitW <= autotileW && tiles.animated)
{ {
/* Static autotile */ /* Static autotile */
for (int j = 0; j < 4; ++j) 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 else
{ {
/* Animated autotile */ /* 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 */ /* Blit tileset */
if (tileset->megaSurface()) if (tileset->megaSurface())
{ {
/* Mega surface tileset */ /* Mega surface tileset */
FBO::unbind(FBO::Draw);
TEX::bind(atlas.gl.tex); TEX::bind(atlas.gl.tex);
SDL_Surface *tsSurf = tileset->megaSurface(); SDL_Surface *tsSurf = tileset->megaSurface();
@ -606,14 +611,18 @@ struct TilemapPrivate
else else
{ {
/* Regular tileset */ /* 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) for (size_t i = 0; i < blits.size(); ++i)
{ {
const TileAtlas::Blit &blitOp = blits[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();
} }
} }

View File

@ -416,7 +416,7 @@ struct WindowPrivate
TEX::allocEmpty(baseTex.width, baseTex.height); TEX::allocEmpty(baseTex.width, baseTex.height);
TEX::unbind(); 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.viewport.pushSet(IntRect(0, 0, baseTex.width, baseTex.height));
glState.clearColor.pushSet(Vec4()); glState.clearColor.pushSet(Vec4());