Skip to content

Commit bcafa5c

Browse files
committed
gl: Enables direct rendering to the back buffer
Allows the engine to render directly to the screen's back buffer, bypassing intermediate framebuffers when possible. This change introduces a new `mDirectTarget` flag to indicate whether the rendering target is the back buffer. When rendering directly, it uses a compose task instead of a blit task, and avoids unnecessary framebuffer operations. This improves rendering performance and reduces memory consumption in scenarios where direct rendering is feasible. Related issues: #3951
1 parent 54e4c4d commit bcafa5c

File tree

10 files changed

+77
-25
lines changed

10 files changed

+77
-25
lines changed

examples/Example.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,9 @@ struct GlWindow : Window
371371
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
372372
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
373373
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
374+
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
375+
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
376+
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
374377
#endif
375378
window = SDL_CreateWindow("ThorVG Example (OpenGL/ES)", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE);
376379
context = SDL_GL_CreateContext(window);

examples/MultiCanvas.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ void runGl()
183183
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
184184
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
185185
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
186+
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
187+
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
188+
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
186189
#endif
187190

188191
auto window = SDL_CreateWindow("ThorVG Example (OpenGL)", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);

src/renderer/gl_engine/tvgGl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
455455
//PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
456456
//PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
457457
//PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
458-
//PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv;
458+
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv;
459459
//PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
460460
//PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
461461
//PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
@@ -783,7 +783,7 @@ bool glInit()
783783
GL_FUNCTION_FETCH(glFramebufferTexture2D, PFNGLFRAMEBUFFERTEXTURE2DPROC);
784784
// GL_FUNCTION_FETCH(glFramebufferTexture3D, PFNGLFRAMEBUFFERTEXTURE3DPROC);
785785
GL_FUNCTION_FETCH(glFramebufferRenderbuffer, PFNGLFRAMEBUFFERRENDERBUFFERPROC);
786-
// GL_FUNCTION_FETCH(glGetFramebufferAttachmentParameteriv, PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC);
786+
GL_FUNCTION_FETCH(glGetFramebufferAttachmentParameteriv, PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC);
787787
// GL_FUNCTION_FETCH(glGenerateMipmap, PFNGLGENERATEMIPMAPPROC);
788788
GL_FUNCTION_FETCH(glBlitFramebuffer, PFNGLBLITFRAMEBUFFERPROC);
789789
GL_FUNCTION_FETCH(glRenderbufferStorageMultisample, PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC);

src/renderer/gl_engine/tvgGl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,7 +1078,7 @@
10781078
//typedef GLenum (*PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target);
10791079
//typedef void (*PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
10801080
//typedef void (*PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
1081-
//typedef void (*PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
1081+
typedef void (*PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
10821082
//typedef void (*PFNGLGENERATEMIPMAPPROC)(GLenum target);
10831083
//typedef void (*PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
10841084
//typedef void *(*PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
@@ -1463,7 +1463,7 @@
14631463
//extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
14641464
//extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
14651465
//extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
1466-
//extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv;
1466+
extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv;
14671467
//extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
14681468
//extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
14691469
//extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;

src/renderer/gl_engine/tvgGlCommon.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#define MIN_GL_STROKE_WIDTH 1.0f
3232
#define MIN_GL_STROKE_ALPHA 0.25f
33+
#define MIN_GL_MSAA_SAMPLES 4
3334

3435
#define MVP_MATRIX(w, h) \
3536
float mvp[4*4] = { \

src/renderer/gl_engine/tvgGlRenderTarget.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,21 @@ GlRenderTarget::~GlRenderTarget()
2929
reset();
3030
}
3131

32-
void GlRenderTarget::init(uint32_t width, uint32_t height, GLint resolveId)
32+
void GlRenderTarget::init(uint32_t width, uint32_t height, GLint resolveId, bool external)
3333
{
3434
if (width == 0 || height == 0) return;
3535

3636
mWidth = width;
3737
mHeight = height;
38+
mExternal = external;
39+
mValid = true;
40+
41+
if (mExternal) {
42+
mFbo = static_cast<GLuint>(resolveId);
43+
mColorBuffer = mDepthStencilBuffer = mResolveFbo = mColorTex = 0;
44+
return;
45+
}
3846

39-
//TODO: fbo is used. maybe we can consider the direct rendering with resolveId as well.
4047
GL_CHECK(glGenFramebuffers(1, &mFbo));
4148

4249
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mFbo));
@@ -78,16 +85,22 @@ void GlRenderTarget::init(uint32_t width, uint32_t height, GLint resolveId)
7885

7986
void GlRenderTarget::reset()
8087
{
81-
if (mFbo == 0) return;
82-
83-
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
84-
GL_CHECK(glDeleteFramebuffers(1, &mFbo));
85-
GL_CHECK(glDeleteRenderbuffers(1, &mColorBuffer));
86-
GL_CHECK(glDeleteRenderbuffers(1, &mDepthStencilBuffer));
87-
GL_CHECK(glDeleteFramebuffers(1, &mResolveFbo));
88-
GL_CHECK(glDeleteTextures(1, &mColorTex));
88+
if (!mValid) return;
89+
90+
if (!mExternal) {
91+
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
92+
if (mFbo != 0) GL_CHECK(glDeleteFramebuffers(1, &mFbo));
93+
if (mColorBuffer != 0) GL_CHECK(glDeleteRenderbuffers(1, &mColorBuffer));
94+
if (mDepthStencilBuffer != 0) GL_CHECK(glDeleteRenderbuffers(1, &mDepthStencilBuffer));
95+
if (mResolveFbo != 0) GL_CHECK(glDeleteFramebuffers(1, &mResolveFbo));
96+
if (mColorTex != 0) GL_CHECK(glDeleteTextures(1, &mColorTex));
97+
}
8998

9099
mFbo = mColorBuffer = mDepthStencilBuffer = mResolveFbo = mColorTex = 0;
100+
mWidth = mHeight = 0;
101+
mViewport = {};
102+
mValid = false;
103+
mExternal = false;
91104
}
92105

93106
GlRenderTargetPool::GlRenderTargetPool(uint32_t maxWidth, uint32_t maxHeight): mMaxWidth(maxWidth), mMaxHeight(maxHeight), mPool() {}

src/renderer/gl_engine/tvgGlRenderTarget.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class GlRenderTarget
3131
GlRenderTarget();
3232
~GlRenderTarget();
3333

34-
void init(uint32_t width, uint32_t height, GLint resolveId);
34+
void init(uint32_t width, uint32_t height, GLint resolveId, bool external = false);
3535
void reset();
3636

3737
GLuint getFboId() { return mFbo; }
@@ -44,12 +44,15 @@ class GlRenderTarget
4444
void setViewport(const RenderRegion& vp) { mViewport = vp; }
4545
const RenderRegion& getViewport() const { return mViewport; }
4646

47-
bool invalid() const { return mFbo == 0; }
47+
bool invalid() const { return !mValid; }
48+
bool internal() const { return !mExternal; }
4849

4950
private:
5051
uint32_t mWidth = 0;
5152
uint32_t mHeight = 0;
5253
RenderRegion mViewport{};
54+
bool mValid = false;
55+
bool mExternal = false;
5356
GLuint mFbo = 0;
5457
GLuint mColorBuffer = 0;
5558
GLuint mDepthStencilBuffer = 0;
@@ -69,4 +72,4 @@ class GlRenderTargetPool {
6972
Array<GlRenderTarget*> mPool;
7073
};
7174

72-
#endif //_TVG_GL_RENDER_RENDER_TARGET_H_
75+
#endif //_TVG_GL_RENDER_RENDER_TARGET_H_

src/renderer/gl_engine/tvgGlRenderTask.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ void GlComposeTask::run()
224224
#endif
225225
// reset scissor box
226226
GL_CHECK(glScissor(0, 0, mFbo->getWidth(), mFbo->getHeight()));
227-
onResolve();
227+
if (mFbo->internal()) onResolve();
228228
}
229229

230230

src/renderer/gl_engine/tvgGlRenderer.cpp

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ void GlRenderer::flush()
5555
clearDisposes();
5656

5757
mRootTarget.reset();
58+
mDirectTarget = false;
5859

5960
ARRAY_FOREACH(p, mComposePool) delete(*p);
6061
mComposePool.clear();
@@ -872,8 +873,31 @@ bool GlRenderer::target(void* context, int32_t id, uint32_t w, uint32_t h, Color
872873

873874
currentContext();
874875

876+
mDirectTarget = (mTargetFboId == 0);
877+
if (mDirectTarget) {
878+
GLint stencilSize = 0;
879+
GLint depthSize = 0;
880+
GL_CHECK(glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencilSize));
881+
GL_CHECK(glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depthSize));
882+
if (stencilSize == 0 || depthSize == 0) {
883+
TVGERR("GL_ENGINE", "Default framebuffer lacks stencil/depth buffers. Falling back to offscreen rendering.");
884+
mDirectTarget = false;
885+
}
886+
GLint maxSamples = 0, sampleBuffers = 0;
887+
GL_CHECK(glGetIntegerv(GL_MAX_SAMPLES, &maxSamples));
888+
GL_CHECK(glGetIntegerv(GL_SAMPLE_BUFFERS, &sampleBuffers));
889+
if (maxSamples < MIN_GL_MSAA_SAMPLES || sampleBuffers == 0) {
890+
TVGERR("GL_ENGINE", "Default framebuffer does not support required MSAA. The quality of the rendered image may be affected.");
891+
} else {
892+
#ifdef GL_MULTISAMPLE
893+
glEnable(GL_MULTISAMPLE);
894+
#endif
895+
TVGLOG("GL_ENGINE", "Default framebuffer supports required MSAA.");
896+
}
897+
}
898+
875899
mRootTarget.setViewport({{0, 0}, {int32_t(surface.w), int32_t(surface.h)}});
876-
mRootTarget.init(surface.w, surface.h, mTargetFboId);
900+
mRootTarget.init(surface.w, surface.h, mTargetFboId, mDirectTarget);
877901

878902
return true;
879903
}
@@ -895,12 +919,16 @@ bool GlRenderer::sync()
895919
GL_CHECK(glEnable(GL_DEPTH_TEST));
896920
GL_CHECK(glDepthFunc(GL_GREATER));
897921

898-
auto task = mRenderPassStack.first()->endRenderPass<GlBlitTask>(mPrograms[RT_Blit], mTargetFboId);
899-
900-
prepareBlitTask(task);
901-
902-
task->mClearBuffer = mClearBuffer;
903-
task->setTargetViewport({{0, 0}, {int32_t(surface.w), int32_t(surface.h)}});
922+
GlRenderTask* task = nullptr;
923+
if (mDirectTarget) {
924+
task = mRenderPassStack.first()->endRenderPass<GlComposeTask>(nullptr, mTargetFboId);
925+
} else {
926+
auto blitTask = mRenderPassStack.first()->endRenderPass<GlBlitTask>(mPrograms[RT_Blit], mTargetFboId);
927+
prepareBlitTask(blitTask);
928+
blitTask->mClearBuffer = mClearBuffer;
929+
blitTask->setTargetViewport({{0, 0}, {int32_t(surface.w), int32_t(surface.h)}});
930+
task = blitTask;
931+
}
904932

905933
if (mGpuBuffer.flushToGPU()) {
906934
mGpuBuffer.bind();

src/renderer/gl_engine/tvgGlRenderer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ struct GlRenderer : RenderMethod
208208

209209
BlendMethod mBlendMethod = BlendMethod::Normal;
210210
bool mClearBuffer = false;
211+
bool mDirectTarget = false;
211212
};
212213

213214
#endif /* _TVG_GL_RENDERER_H_ */

0 commit comments

Comments
 (0)