From 6e901fd8fc5b89e52dc44fd87a782c4f47c9c3f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Tue, 25 Aug 2020 23:27:40 +0200 Subject: GPUFramebuffer: Make GPUFrameBuffer an opaque type This is in preparation of the Framebuffer GL backend. This is a just changing types and moving some code. No logic is changed... almost... it just removes the context attach. i.e: `gpu_context_add/remove_framebuffer()` This is not needed for now and was even disabled in release. This is part of T68990. --- source/blender/gpu/intern/gpu_context.cc | 34 --- source/blender/gpu/intern/gpu_context_private.hh | 7 +- source/blender/gpu/intern/gpu_framebuffer.cc | 239 +++++++++------------ .../blender/gpu/intern/gpu_framebuffer_private.hh | 94 ++++++++ 4 files changed, 195 insertions(+), 179 deletions(-) create mode 100644 source/blender/gpu/intern/gpu_framebuffer_private.hh (limited to 'source/blender/gpu/intern') diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc index ef02ec24a00..9b4705ae6a3 100644 --- a/source/blender/gpu/intern/gpu_context.cc +++ b/source/blender/gpu/intern/gpu_context.cc @@ -185,40 +185,6 @@ void GPU_tex_free(GLuint tex_id) static_cast(backend)->tex_free(tex_id); } -/* GPUBatch & GPUFrameBuffer contains respectively VAO & FBO indices - * which are not shared across contexts. So we need to keep track of - * ownership. */ - -void gpu_context_add_framebuffer(GPUContext *ctx, GPUFrameBuffer *fb) -{ -#ifdef DEBUG - BLI_assert(ctx); - static_cast(ctx)->framebuffer_register(fb); -#else - UNUSED_VARS(ctx, fb); -#endif -} - -void gpu_context_remove_framebuffer(GPUContext *ctx, GPUFrameBuffer *fb) -{ -#ifdef DEBUG - BLI_assert(ctx); - static_cast(ctx)->framebuffer_unregister(fb); -#else - UNUSED_VARS(ctx, fb); -#endif -} - -void gpu_context_active_framebuffer_set(GPUContext *ctx, GPUFrameBuffer *fb) -{ - ctx->current_fbo = fb; -} - -GPUFrameBuffer *gpu_context_active_framebuffer_get(GPUContext *ctx) -{ - return ctx->current_fbo; -} - struct GPUMatrixState *gpu_context_active_matrix_state_get() { BLI_assert(active_ctx); diff --git a/source/blender/gpu/intern/gpu_context_private.hh b/source/blender/gpu/intern/gpu_context_private.hh index e8c9c976e9a..d18d18dc97b 100644 --- a/source/blender/gpu/intern/gpu_context_private.hh +++ b/source/blender/gpu/intern/gpu_context_private.hh @@ -29,6 +29,7 @@ #include "GPU_context.h" +#include "gpu_framebuffer_private.hh" #include "gpu_shader_private.hh" #include "gpu_state_private.hh" @@ -38,14 +39,13 @@ #include #include -struct GPUFrameBuffer; struct GPUMatrixState; struct GPUContext { public: /** State managment */ blender::gpu::Shader *shader = NULL; - GPUFrameBuffer *current_fbo = NULL; + blender::gpu::FrameBuffer *active_fb = NULL; GPUMatrixState *matrix_state = NULL; blender::gpu::GPUStateManager *state_manager = NULL; @@ -82,9 +82,6 @@ void GPU_tex_free(GLuint tex_id); void GPU_vao_free(GLuint vao_id, GPUContext *ctx); void GPU_fbo_free(GLuint fbo_id, GPUContext *ctx); -void gpu_context_add_framebuffer(GPUContext *ctx, struct GPUFrameBuffer *fb); -void gpu_context_remove_framebuffer(GPUContext *ctx, struct GPUFrameBuffer *fb); - void gpu_context_active_framebuffer_set(GPUContext *ctx, struct GPUFrameBuffer *fb); struct GPUFrameBuffer *gpu_context_active_framebuffer_get(GPUContext *ctx); diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc index 67320ed61b6..2f39bb37acd 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.cc +++ b/source/blender/gpu/intern/gpu_framebuffer.cc @@ -29,51 +29,15 @@ #include "GPU_batch.h" #include "GPU_extensions.h" -#include "GPU_framebuffer.h" #include "GPU_shader.h" #include "GPU_texture.h" #include "gpu_context_private.hh" #include "gpu_private.h" -typedef enum { - GPU_FB_DEPTH_ATTACHMENT = 0, - GPU_FB_DEPTH_STENCIL_ATTACHMENT, - GPU_FB_COLOR_ATTACHMENT0, - GPU_FB_COLOR_ATTACHMENT1, - GPU_FB_COLOR_ATTACHMENT2, - GPU_FB_COLOR_ATTACHMENT3, - GPU_FB_COLOR_ATTACHMENT4, - GPU_FB_COLOR_ATTACHMENT5, - /* Number of maximum output slots. - * We support 6 outputs for now (usually we wouldn't need more to preserve fill rate). */ - /* Keep in mind that GL max is GL_MAX_DRAW_BUFFERS and is at least 8, corresponding to - * the maximum number of COLOR attachments specified by glDrawBuffers. */ - GPU_FB_MAX_ATTACHEMENT, -} GPUAttachmentType; - -#define FOREACH_ATTACHMENT_RANGE(att, _start, _end) \ - for (GPUAttachmentType att = static_cast(_start); att < _end; \ - att = static_cast(att + 1)) - -#define GPU_FB_MAX_COLOR_ATTACHMENT (GPU_FB_MAX_ATTACHEMENT - GPU_FB_COLOR_ATTACHMENT0) - -#define GPU_FB_DIRTY_DRAWBUFFER (1 << 15) - -#define GPU_FB_ATTACHEMENT_IS_DIRTY(flag, type) ((flag & (1 << type)) != 0) -#define GPU_FB_ATTACHEMENT_SET_DIRTY(flag, type) (flag |= (1 << type)) - -struct GPUFrameBuffer { - GPUContext *ctx; - GLuint object; - GPUAttachment attachments[GPU_FB_MAX_ATTACHEMENT]; - uint16_t dirty_flag; - int width, height; - bool multisample; - /* TODO Check that we always use the right context when binding - * (FBOs are not shared across ogl contexts). */ - // void *ctx; -}; +#include "gpu_framebuffer_private.hh" + +using namespace blender::gpu; static GLenum convert_attachment_type_to_gl(GPUAttachmentType type) { @@ -122,20 +86,6 @@ static GLenum convert_buffer_bits_to_gl(eGPUFrameBufferBits bits) return mask; } -static GPUTexture *framebuffer_get_depth_tex(GPUFrameBuffer *fb) -{ - if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex) { - return fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex; - } - - return fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex; -} - -static GPUTexture *framebuffer_get_color_tex(GPUFrameBuffer *fb, int slot) -{ - return fb->attachments[GPU_FB_COLOR_ATTACHMENT0 + slot].tex; -} - static void gpu_print_framebuffer_error(GLenum status, char err_out[256]) { const char *format = "GPUFrameBuffer: framebuffer status %s\n"; @@ -186,19 +136,7 @@ void gpu_framebuffer_module_exit(void) GPUFrameBuffer *GPU_framebuffer_active_get(void) { GPUContext *ctx = GPU_context_active_get(); - if (ctx) { - return gpu_context_active_framebuffer_get(ctx); - } - - return 0; -} - -static void gpu_framebuffer_current_set(GPUFrameBuffer *fb) -{ - GPUContext *ctx = GPU_context_active_get(); - if (ctx) { - gpu_context_active_framebuffer_set(ctx, fb); - } + return reinterpret_cast(ctx ? ctx->active_fb : NULL); } /* GPUFrameBuffer */ @@ -207,42 +145,46 @@ GPUFrameBuffer *GPU_framebuffer_create(void) { /* We generate the FB object later at first use in order to * create the framebuffer in the right opengl context. */ - return (GPUFrameBuffer *)MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer"); + return (GPUFrameBuffer *)new FrameBuffer(); } -static void gpu_framebuffer_init(GPUFrameBuffer *fb) +static void gpu_framebuffer_init(FrameBuffer *fb) { fb->object = GPU_fbo_alloc(); fb->ctx = GPU_context_active_get(); - gpu_context_add_framebuffer(fb->ctx, fb); + /* Not really needed for now. */ + // gpu_context_add_framebuffer(fb->ctx, fb); } -void GPU_framebuffer_free(GPUFrameBuffer *fb) +void GPU_framebuffer_free(GPUFrameBuffer *gpu_fb) { + FrameBuffer *fb = reinterpret_cast(gpu_fb); for (int i_type = 0; i_type < GPU_FB_MAX_ATTACHEMENT; i_type++) { GPUAttachmentType type = static_cast(i_type); if (fb->attachments[type].tex != NULL) { - GPU_framebuffer_texture_detach(fb, fb->attachments[type].tex); + GPU_framebuffer_texture_detach(gpu_fb, fb->attachments[type].tex); } } if (fb->object != 0) { /* This restores the framebuffer if it was bound */ GPU_fbo_free(fb->object, fb->ctx); - gpu_context_remove_framebuffer(fb->ctx, fb); + /* Not really needed for now. */ + // gpu_context_remove_framebuffer(fb->ctx, fb); } - if (GPU_framebuffer_active_get() == fb) { - gpu_framebuffer_current_set(NULL); + /* TODO(fclem) check if bound in its associated context context. */ + if (GPU_framebuffer_active_get() == gpu_fb) { + GPU_context_active_get()->active_fb = NULL; } - MEM_freeN(fb); + delete fb; } /* ---------- Attach ----------- */ static void gpu_framebuffer_texture_attach_ex( - GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip) + FrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip) { if (slot >= GPU_FB_MAX_COLOR_ATTACHMENT) { fprintf(stderr, @@ -253,6 +195,7 @@ static void gpu_framebuffer_texture_attach_ex( return; } + GPUFrameBuffer *gpufb = reinterpret_cast(fb); GPUAttachmentType type = attachment_type_from_tex(tex, slot); GPUAttachment *attachment = &fb->attachments[type]; @@ -260,11 +203,11 @@ static void gpu_framebuffer_texture_attach_ex( return; /* Exact same texture already bound here. */ } if (attachment->tex != NULL) { - GPU_framebuffer_texture_detach(fb, attachment->tex); + GPU_framebuffer_texture_detach(gpufb, attachment->tex); } if (attachment->tex == NULL) { - GPU_texture_attach_framebuffer(tex, fb, type); + GPU_texture_attach_framebuffer(tex, gpufb, type); } attachment->tex = tex; @@ -273,30 +216,34 @@ static void gpu_framebuffer_texture_attach_ex( GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type); } -void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip) +void GPU_framebuffer_texture_attach(GPUFrameBuffer *gpu_fb, GPUTexture *tex, int slot, int mip) { + FrameBuffer *fb = reinterpret_cast(gpu_fb); gpu_framebuffer_texture_attach_ex(fb, tex, slot, -1, mip); } void GPU_framebuffer_texture_layer_attach( - GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip) + GPUFrameBuffer *gpu_fb, GPUTexture *tex, int slot, int layer, int mip) { + FrameBuffer *fb = reinterpret_cast(gpu_fb); /* NOTE: We could support 1D ARRAY texture. */ BLI_assert(GPU_texture_target(tex) == GL_TEXTURE_2D_ARRAY); gpu_framebuffer_texture_attach_ex(fb, tex, slot, layer, mip); } void GPU_framebuffer_texture_cubeface_attach( - GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip) + GPUFrameBuffer *gpu_fb, GPUTexture *tex, int slot, int face, int mip) { + FrameBuffer *fb = reinterpret_cast(gpu_fb); BLI_assert(GPU_texture_cube(tex)); gpu_framebuffer_texture_attach_ex(fb, tex, slot, face, mip); } /* ---------- Detach ----------- */ -void GPU_framebuffer_texture_detach_slot(GPUFrameBuffer *fb, GPUTexture *tex, int type) +void GPU_framebuffer_texture_detach_slot(GPUFrameBuffer *gpu_fb, GPUTexture *tex, int type) { + FrameBuffer *fb = reinterpret_cast(gpu_fb); GPUAttachment *attachment = &fb->attachments[type]; if (attachment->tex != tex) { @@ -312,10 +259,10 @@ void GPU_framebuffer_texture_detach_slot(GPUFrameBuffer *fb, GPUTexture *tex, in GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type); } -void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex) +void GPU_framebuffer_texture_detach(GPUFrameBuffer *gpu_fb, GPUTexture *tex) { - GPUAttachmentType type = (GPUAttachmentType)GPU_texture_detach_framebuffer(tex, fb); - GPU_framebuffer_texture_detach_slot(fb, tex, type); + GPUAttachmentType type = (GPUAttachmentType)GPU_texture_detach_framebuffer(tex, gpu_fb); + GPU_framebuffer_texture_detach_slot(gpu_fb, tex, type); } /* ---------- Config (Attach & Detach) ----------- */ @@ -326,8 +273,11 @@ void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex) * Setting GPUAttachment.mip to -1 will leave the texture in this slot. * Setting GPUAttachment.tex to NULL will detach the texture in this slot. */ -void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_len) +void GPU_framebuffer_config_array(GPUFrameBuffer *gpu_fb, + const GPUAttachment *config, + int config_len) { + FrameBuffer *fb = reinterpret_cast(gpu_fb); if (config[0].tex) { BLI_assert(GPU_texture_depth(config[0].tex)); gpu_framebuffer_texture_attach_ex(fb, config[0].tex, 0, config[0].layer, config[0].mip); @@ -336,10 +286,10 @@ void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *confi /* Leave texture attached */ } else if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex != NULL) { - GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex); + GPU_framebuffer_texture_detach(gpu_fb, fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex); } else if (fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex != NULL) { - GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex); + GPU_framebuffer_texture_detach(gpu_fb, fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex); } int slot = 0; @@ -349,9 +299,9 @@ void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *confi gpu_framebuffer_texture_attach_ex(fb, config[i].tex, slot, config[i].layer, config[i].mip); } else if (config[i].mip != -1) { - GPUTexture *tex = framebuffer_get_color_tex(fb, slot); + GPUTexture *tex = fb->color_tex(slot); if (tex != NULL) { - GPU_framebuffer_texture_detach(fb, tex); + GPU_framebuffer_texture_detach(gpu_fb, tex); } } } @@ -389,12 +339,12 @@ static void gpu_framebuffer_attachment_detach(GPUAttachment *UNUSED(attachment), glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, 0, 0); } -static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb) +static void gpu_framebuffer_update_attachments(FrameBuffer *fb) { GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT]; int numslots = 0; - BLI_assert(GPU_framebuffer_active_get() == fb); + BLI_assert(GPU_context_active_get()->active_fb == fb); /* Update attachments */ FOREACH_ATTACHMENT_RANGE(type, 0, GPU_FB_MAX_ATTACHEMENT) @@ -440,12 +390,12 @@ static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb) * If there is an empty color slot between the color slots, * all textures after this slot are apparently skipped/discarded. */ -static void gpu_framebuffer_update_attachments_and_fill_empty_slots(GPUFrameBuffer *fb) +static void gpu_framebuffer_update_attachments_and_fill_empty_slots(FrameBuffer *fb) { GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT]; int dummy_tex = 0; - BLI_assert(GPU_framebuffer_active_get() == fb); + BLI_assert(GPU_context_active_get()->active_fb == fb); /* Update attachments */ for (int i_type = GPU_FB_MAX_ATTACHEMENT - 1; i_type >= 0; --i_type) { @@ -500,10 +450,10 @@ static struct { uint top; } FrameBufferStack = {{0}}; -static void gpuPushFrameBuffer(GPUFrameBuffer *fbo) +static void gpuPushFrameBuffer(GPUFrameBuffer *fb) { BLI_assert(FrameBufferStack.top < FRAMEBUFFER_STACK_DEPTH); - FrameBufferStack.framebuffers[FrameBufferStack.top] = fbo; + FrameBufferStack.framebuffers[FrameBufferStack.top] = fb; FrameBufferStack.top++; } @@ -516,13 +466,15 @@ static GPUFrameBuffer *gpuPopFrameBuffer(void) #undef FRAMEBUFFER_STACK_DEPTH -void GPU_framebuffer_bind(GPUFrameBuffer *fb) +void GPU_framebuffer_bind(GPUFrameBuffer *gpu_fb) { + FrameBuffer *fb = reinterpret_cast(gpu_fb); + if (fb->object == 0) { gpu_framebuffer_init(fb); } - if (GPU_framebuffer_active_get() != fb) { + if (GPU_framebuffer_active_get() != gpu_fb) { glBindFramebuffer(GL_FRAMEBUFFER, fb->object); glEnable(GL_FRAMEBUFFER_SRGB); @@ -532,7 +484,7 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb) GPU_shader_set_framebuffer_srgb_target(is_srgb_target); } - gpu_framebuffer_current_set(fb); + GPU_context_active_get()->active_fb = fb; if (fb->dirty_flag != 0) { if (GPU_unused_fb_slot_workaround()) { @@ -556,9 +508,11 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb) } /* Workaround for binding a srgb framebuffer without doing the srgb transform. */ -void GPU_framebuffer_bind_no_srgb(GPUFrameBuffer *fb) +void GPU_framebuffer_bind_no_srgb(GPUFrameBuffer *gpu_fb) { - GPU_framebuffer_bind(fb); + FrameBuffer *fb = reinterpret_cast(gpu_fb); + + GPU_framebuffer_bind(gpu_fb); glDisable(GL_FRAMEBUFFER_SRGB); @@ -571,21 +525,22 @@ void GPU_framebuffer_restore(void) { if (GPU_framebuffer_active_get() != NULL) { glBindFramebuffer(GL_FRAMEBUFFER, GPU_framebuffer_default()); - gpu_framebuffer_current_set(NULL); + GPU_context_active_get()->active_fb = NULL; glDisable(GL_FRAMEBUFFER_SRGB); GPU_shader_set_framebuffer_srgb_target(false); } } -bool GPU_framebuffer_bound(GPUFrameBuffer *fb) +bool GPU_framebuffer_bound(GPUFrameBuffer *gpu_fb) { - return (fb == GPU_framebuffer_active_get()) && (fb->object != 0); + FrameBuffer *fb = reinterpret_cast(gpu_fb); + return (gpu_fb == GPU_framebuffer_active_get()) && (fb->object != 0); } -bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]) +bool GPU_framebuffer_check_valid(GPUFrameBuffer *gpu_fb, char err_out[256]) { - if (!GPU_framebuffer_bound(fb)) { - GPU_framebuffer_bind(fb); + if (!GPU_framebuffer_bound(gpu_fb)) { + GPU_framebuffer_bind(gpu_fb); } GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -607,20 +562,20 @@ bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]) ((void)0) /* Needs to be done after binding. */ -void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int w, int h) +void GPU_framebuffer_viewport_set(GPUFrameBuffer *gpu_fb, int x, int y, int w, int h) { - CHECK_FRAMEBUFFER_IS_BOUND(fb); + CHECK_FRAMEBUFFER_IS_BOUND(gpu_fb); GPU_viewport(x, y, w, h); } -void GPU_framebuffer_clear(GPUFrameBuffer *fb, +void GPU_framebuffer_clear(GPUFrameBuffer *gpu_fb, eGPUFrameBufferBits buffers, const float clear_col[4], float clear_depth, uint clear_stencil) { - CHECK_FRAMEBUFFER_IS_BOUND(fb); + CHECK_FRAMEBUFFER_IS_BOUND(gpu_fb); /* Save and restore the state. */ eGPUWriteMask write_mask = GPU_write_mask_get(); @@ -656,9 +611,11 @@ void GPU_framebuffer_clear(GPUFrameBuffer *fb, } /* Clear all textures bound to this framebuffer with a different color. */ -void GPU_framebuffer_multi_clear(GPUFrameBuffer *fb, const float (*clear_cols)[4]) +void GPU_framebuffer_multi_clear(GPUFrameBuffer *gpu_fb, const float (*clear_cols)[4]) { - CHECK_FRAMEBUFFER_IS_BOUND(fb); + CHECK_FRAMEBUFFER_IS_BOUND(gpu_fb); + + FrameBuffer *fb = reinterpret_cast(gpu_fb); /* Save and restore the state. */ eGPUWriteMask write_mask = GPU_write_mask_get(); @@ -675,9 +632,9 @@ void GPU_framebuffer_multi_clear(GPUFrameBuffer *fb, const float (*clear_cols)[4 GPU_write_mask(write_mask); } -void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data) +void GPU_framebuffer_read_depth(GPUFrameBuffer *gpu_fb, int x, int y, int w, int h, float *data) { - CHECK_FRAMEBUFFER_IS_BOUND(fb); + CHECK_FRAMEBUFFER_IS_BOUND(gpu_fb); GLenum type = GL_DEPTH_COMPONENT; glReadBuffer(GL_COLOR_ATTACHMENT0); /* This is OK! */ @@ -735,7 +692,7 @@ static void gpu_framebuffer_read_color_ex( glReadPixels(x, y, w, h, type, gl_format, data); } -void GPU_framebuffer_read_color(GPUFrameBuffer *fb, +void GPU_framebuffer_read_color(GPUFrameBuffer *gpu_fb, int x, int y, int w, @@ -745,40 +702,40 @@ void GPU_framebuffer_read_color(GPUFrameBuffer *fb, eGPUDataFormat format, void *data) { - CHECK_FRAMEBUFFER_IS_BOUND(fb); + CHECK_FRAMEBUFFER_IS_BOUND(gpu_fb); gpu_framebuffer_read_color_ex( x, y, w, h, channels, GL_COLOR_ATTACHMENT0 + slot, format, (float *)data); } /* read_slot and write_slot are only used for color buffers. */ -void GPU_framebuffer_blit(GPUFrameBuffer *fb_read, +void GPU_framebuffer_blit(GPUFrameBuffer *gpufb_read, int read_slot, - GPUFrameBuffer *fb_write, + GPUFrameBuffer *gpufb_write, int write_slot, eGPUFrameBufferBits blit_buffers) { + FrameBuffer *fb_read = reinterpret_cast(gpufb_read); + FrameBuffer *fb_write = reinterpret_cast(gpufb_write); BLI_assert(blit_buffers != 0); - GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get(); + FrameBuffer *prev_fb = GPU_context_active_get()->active_fb; /* Framebuffers must be up to date. This simplify this function. */ if (fb_read->dirty_flag != 0 || fb_read->object == 0) { - GPU_framebuffer_bind(fb_read); + GPU_framebuffer_bind(gpufb_read); } if (fb_write->dirty_flag != 0 || fb_write->object == 0) { - GPU_framebuffer_bind(fb_write); + GPU_framebuffer_bind(gpufb_write); } const bool do_color = (blit_buffers & GPU_COLOR_BIT); const bool do_depth = (blit_buffers & GPU_DEPTH_BIT); const bool do_stencil = (blit_buffers & GPU_STENCIL_BIT); - GPUTexture *read_tex = ((do_depth || do_stencil) ? - framebuffer_get_depth_tex(fb_read) : - framebuffer_get_color_tex(fb_read, read_slot)); - GPUTexture *write_tex = ((do_depth || do_stencil) ? - framebuffer_get_depth_tex(fb_write) : - framebuffer_get_color_tex(fb_write, read_slot)); + GPUTexture *read_tex = ((do_depth || do_stencil) ? fb_read->depth_tex() : + fb_read->color_tex(read_slot)); + GPUTexture *write_tex = ((do_depth || do_stencil) ? fb_write->depth_tex() : + fb_write->color_tex(read_slot)); if (do_depth) { BLI_assert(GPU_texture_depth(read_tex) && GPU_texture_depth(write_tex)); @@ -821,15 +778,15 @@ void GPU_framebuffer_blit(GPUFrameBuffer *fb_read, /* Restore previous framebuffer */ if (fb_write == prev_fb) { - GPU_framebuffer_bind(fb_write); /* To update drawbuffers */ + GPU_framebuffer_bind(gpufb_write); /* To update drawbuffers */ } else if (prev_fb) { glBindFramebuffer(GL_FRAMEBUFFER, prev_fb->object); - gpu_framebuffer_current_set(prev_fb); + GPU_context_active_get()->active_fb = prev_fb; } else { glBindFramebuffer(GL_FRAMEBUFFER, GPU_framebuffer_default()); - gpu_framebuffer_current_set(NULL); + GPU_context_active_get()->active_fb = NULL; } } @@ -838,19 +795,21 @@ void GPU_framebuffer_blit(GPUFrameBuffer *fb_read, * input. This function only takes care of the correct texture handling. It execute the callback * for each texture level. */ -void GPU_framebuffer_recursive_downsample(GPUFrameBuffer *fb, +void GPU_framebuffer_recursive_downsample(GPUFrameBuffer *gpu_fb, int max_lvl, void (*callback)(void *userData, int level), void *userData) { + GPUContext *ctx = GPU_context_active_get(); + FrameBuffer *fb = reinterpret_cast(gpu_fb); /* Framebuffer must be up to date and bound. This simplify this function. */ - if (GPU_framebuffer_active_get() != fb || fb->dirty_flag != 0 || fb->object == 0) { - GPU_framebuffer_bind(fb); + if (ctx->active_fb != fb || fb->dirty_flag != 0 || fb->object == 0) { + GPU_framebuffer_bind(gpu_fb); } /* HACK: We make the framebuffer appear not bound in order to * not trigger any error in GPU_texture_bind(). */ - GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get(); - gpu_framebuffer_current_set(NULL); + FrameBuffer *prev_fb = ctx->active_fb; + ctx->active_fb = NULL; int levels = floor(log2(max_ii(fb->width, fb->height))); max_lvl = min_ii(max_lvl, levels); @@ -908,7 +867,7 @@ void GPU_framebuffer_recursive_downsample(GPUFrameBuffer *fb, } } - gpu_framebuffer_current_set(prev_fb); + ctx->active_fb = prev_fb; } /* GPUOffScreen */ @@ -1033,7 +992,7 @@ void GPU_offscreen_bind(GPUOffScreen *ofs, bool save) GPU_viewport_size_get_i(ofs->saved_viewport); GPUFrameBuffer *fb = GPU_framebuffer_active_get(); - gpuPushFrameBuffer(fb); + gpuPushFrameBuffer(reinterpret_cast(fb)); } GPUFrameBuffer *ofs_fb = gpu_offscreen_fb_get(ofs); GPU_framebuffer_bind(ofs_fb); @@ -1067,7 +1026,7 @@ void GPU_offscreen_draw_to_screen(GPUOffScreen *ofs, int x, int y) GPU_context_active_get()->state_manager->apply_state(); - GPUFrameBuffer *ofs_fb = gpu_offscreen_fb_get(ofs); + FrameBuffer *ofs_fb = reinterpret_cast(gpu_offscreen_fb_get(ofs)); glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs_fb->object); GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); @@ -1157,4 +1116,4 @@ void GPU_backbuffer_bind(eGPUBackBuffer buffer) else if (buffer == GPU_BACKBUFFER_RIGHT) { glDrawBuffer(GL_BACK_RIGHT); } -} +} \ No newline at end of file diff --git a/source/blender/gpu/intern/gpu_framebuffer_private.hh b/source/blender/gpu/intern/gpu_framebuffer_private.hh new file mode 100644 index 00000000000..cc5ae048c7c --- /dev/null +++ b/source/blender/gpu/intern/gpu_framebuffer_private.hh @@ -0,0 +1,94 @@ +/* + * This program 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. + * + * This program 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "MEM_guardedalloc.h" + +#include "GPU_framebuffer.h" + +#include "glew-mx.h" /* For GLuint. To remove. */ + +struct GPUTexture; + +typedef enum { + GPU_FB_DEPTH_ATTACHMENT = 0, + GPU_FB_DEPTH_STENCIL_ATTACHMENT, + GPU_FB_COLOR_ATTACHMENT0, + GPU_FB_COLOR_ATTACHMENT1, + GPU_FB_COLOR_ATTACHMENT2, + GPU_FB_COLOR_ATTACHMENT3, + GPU_FB_COLOR_ATTACHMENT4, + GPU_FB_COLOR_ATTACHMENT5, + /* Number of maximum output slots. + * We support 6 outputs for now (usually we wouldn't need more to preserve fill rate). */ + /* Keep in mind that GL max is GL_MAX_DRAW_BUFFERS and is at least 8, corresponding to + * the maximum number of COLOR attachments specified by glDrawBuffers. */ + GPU_FB_MAX_ATTACHEMENT, +} GPUAttachmentType; + +namespace blender { +namespace gpu { + +#define FOREACH_ATTACHMENT_RANGE(att, _start, _end) \ + for (GPUAttachmentType att = static_cast(_start); att < _end; \ + att = static_cast(att + 1)) + +#define GPU_FB_MAX_COLOR_ATTACHMENT (GPU_FB_MAX_ATTACHEMENT - GPU_FB_COLOR_ATTACHMENT0) + +#define GPU_FB_DIRTY_DRAWBUFFER (1 << 15) + +#define GPU_FB_ATTACHEMENT_IS_DIRTY(flag, type) ((flag & (1 << type)) != 0) +#define GPU_FB_ATTACHEMENT_SET_DIRTY(flag, type) (flag |= (1 << type)) + +class FrameBuffer { + public: + GPUContext *ctx; + GLuint object; + GPUAttachment attachments[GPU_FB_MAX_ATTACHEMENT]; + uint16_t dirty_flag; + int width, height; + bool multisample; + /* TODO Check that we always use the right context when binding + * (FBOs are not shared across ogl contexts). */ + // void *ctx; + + public: + GPUTexture *depth_tex(void) const + { + if (attachments[GPU_FB_DEPTH_ATTACHMENT].tex) { + return attachments[GPU_FB_DEPTH_ATTACHMENT].tex; + } + return attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex; + }; + + GPUTexture *color_tex(int slot) const + { + return attachments[GPU_FB_COLOR_ATTACHMENT0 + slot].tex; + }; + + MEM_CXX_CLASS_ALLOC_FUNCS("FrameBuffer") +}; + +} // namespace gpu +} // namespace blender -- cgit v1.2.3