GLMeta: Add framebuffer blitting support
This commit is contained in:
parent
7ad6b7b5df
commit
a26c73930d
|
@ -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,
|
||||||
|
|
|
@ -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 */ \
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
142
src/graphics.cpp
142
src/graphics.cpp
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue