Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/gpu/intern/gpu_framebuffer.c
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/gpu/intern/gpu_framebuffer.c')
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c1305
1 files changed, 659 insertions, 646 deletions
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index c5ed3f8e01d..bd4572cc643 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -27,7 +27,6 @@
#include "BLI_utildefines.h"
#include "BLI_math_base.h"
-
#include "GPU_batch.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
@@ -40,18 +39,18 @@
#include "gpu_context_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,
- /* Number of maximum output slots.
- * We support 5 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,
+ 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,
+ /* Number of maximum output slots.
+ * We support 5 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 GPU_FB_MAX_COLOR_ATTACHMENT (GPU_FB_MAX_ATTACHEMENT - GPU_FB_COLOR_ATTACHMENT0)
@@ -62,102 +61,100 @@ typedef enum {
#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;
+ 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;
};
static GLenum convert_attachment_type_to_gl(GPUAttachmentType type)
{
- static const GLenum table[] = {
- [GPU_FB_DEPTH_ATTACHMENT] = GL_DEPTH_ATTACHMENT,
- [GPU_FB_DEPTH_STENCIL_ATTACHMENT] = GL_DEPTH_STENCIL_ATTACHMENT,
- [GPU_FB_COLOR_ATTACHMENT0] = GL_COLOR_ATTACHMENT0,
- [GPU_FB_COLOR_ATTACHMENT1] = GL_COLOR_ATTACHMENT1,
- [GPU_FB_COLOR_ATTACHMENT2] = GL_COLOR_ATTACHMENT2,
- [GPU_FB_COLOR_ATTACHMENT3] = GL_COLOR_ATTACHMENT3,
- [GPU_FB_COLOR_ATTACHMENT4] = GL_COLOR_ATTACHMENT4,
- };
- return table[type];
+ static const GLenum table[] = {
+ [GPU_FB_DEPTH_ATTACHMENT] = GL_DEPTH_ATTACHMENT,
+ [GPU_FB_DEPTH_STENCIL_ATTACHMENT] = GL_DEPTH_STENCIL_ATTACHMENT,
+ [GPU_FB_COLOR_ATTACHMENT0] = GL_COLOR_ATTACHMENT0,
+ [GPU_FB_COLOR_ATTACHMENT1] = GL_COLOR_ATTACHMENT1,
+ [GPU_FB_COLOR_ATTACHMENT2] = GL_COLOR_ATTACHMENT2,
+ [GPU_FB_COLOR_ATTACHMENT3] = GL_COLOR_ATTACHMENT3,
+ [GPU_FB_COLOR_ATTACHMENT4] = GL_COLOR_ATTACHMENT4,
+ };
+ return table[type];
}
static GPUAttachmentType attachment_type_from_tex(GPUTexture *tex, int slot)
{
- switch (GPU_texture_format(tex)) {
- case GPU_DEPTH_COMPONENT32F:
- case GPU_DEPTH_COMPONENT24:
- case GPU_DEPTH_COMPONENT16:
- return GPU_FB_DEPTH_ATTACHMENT;
- case GPU_DEPTH24_STENCIL8:
- case GPU_DEPTH32F_STENCIL8:
- return GPU_FB_DEPTH_STENCIL_ATTACHMENT;
- default:
- return GPU_FB_COLOR_ATTACHMENT0 + slot;
- }
+ switch (GPU_texture_format(tex)) {
+ case GPU_DEPTH_COMPONENT32F:
+ case GPU_DEPTH_COMPONENT24:
+ case GPU_DEPTH_COMPONENT16:
+ return GPU_FB_DEPTH_ATTACHMENT;
+ case GPU_DEPTH24_STENCIL8:
+ case GPU_DEPTH32F_STENCIL8:
+ return GPU_FB_DEPTH_STENCIL_ATTACHMENT;
+ default:
+ return GPU_FB_COLOR_ATTACHMENT0 + slot;
+ }
}
static GLenum convert_buffer_bits_to_gl(eGPUFrameBufferBits bits)
{
- GLbitfield mask = 0;
- mask |= (bits & GPU_DEPTH_BIT) ? GL_DEPTH_BUFFER_BIT : 0;
- mask |= (bits & GPU_STENCIL_BIT) ? GL_STENCIL_BUFFER_BIT : 0;
- mask |= (bits & GPU_COLOR_BIT) ? GL_COLOR_BUFFER_BIT : 0;
- return mask;
+ GLbitfield mask = 0;
+ mask |= (bits & GPU_DEPTH_BIT) ? GL_DEPTH_BUFFER_BIT : 0;
+ mask |= (bits & GPU_STENCIL_BIT) ? GL_STENCIL_BUFFER_BIT : 0;
+ mask |= (bits & GPU_COLOR_BIT) ? GL_COLOR_BUFFER_BIT : 0;
+ 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;
- else
- return fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex;
+ if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex)
+ return fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex;
+ else
+ 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;
+ 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";
- const char *err = "unknown";
+ const char *format = "GPUFrameBuffer: framebuffer status %s\n";
+ const char *err = "unknown";
#define format_status(X) \
- case GL_FRAMEBUFFER_##X: err = "GL_FRAMEBUFFER_"#X; \
- break;
-
- switch (status) {
- /* success */
- format_status(COMPLETE)
- /* errors shared by OpenGL desktop & ES */
- format_status(INCOMPLETE_ATTACHMENT)
- format_status(INCOMPLETE_MISSING_ATTACHMENT)
- format_status(UNSUPPORTED)
+ case GL_FRAMEBUFFER_##X: \
+ err = "GL_FRAMEBUFFER_" #X; \
+ break;
+
+ switch (status) {
+ /* success */
+ format_status(COMPLETE)
+ /* errors shared by OpenGL desktop & ES */
+ format_status(INCOMPLETE_ATTACHMENT) format_status(INCOMPLETE_MISSING_ATTACHMENT)
+ format_status(UNSUPPORTED)
#if 0 /* for OpenGL ES only */
- format_status(INCOMPLETE_DIMENSIONS)
+ format_status(INCOMPLETE_DIMENSIONS)
#else /* for desktop GL only */
- format_status(INCOMPLETE_DRAW_BUFFER)
- format_status(INCOMPLETE_READ_BUFFER)
- format_status(INCOMPLETE_MULTISAMPLE)
- format_status(UNDEFINED)
+ format_status(INCOMPLETE_DRAW_BUFFER) format_status(INCOMPLETE_READ_BUFFER)
+ format_status(INCOMPLETE_MULTISAMPLE) format_status(UNDEFINED)
#endif
- }
+ }
#undef format_status
- if (err_out) {
- BLI_snprintf(err_out, 256, format, err);
- }
- else {
- fprintf(stderr, format, err);
- }
+ if (err_out) {
+ BLI_snprintf(err_out, 256, format, err);
+ }
+ else {
+ fprintf(stderr, format, err);
+ }
}
void gpu_framebuffer_module_init(void)
@@ -170,133 +167,137 @@ 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);
- }
- else {
- return 0;
- }
+ GPUContext *ctx = GPU_context_active_get();
+ if (ctx) {
+ return gpu_context_active_framebuffer_get(ctx);
+ }
+ else {
+ 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);
- }
+ GPUContext *ctx = GPU_context_active_get();
+ if (ctx) {
+ gpu_context_active_framebuffer_set(ctx, fb);
+ }
}
/* GPUFrameBuffer */
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 MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
+ /* We generate the FB object later at first use in order to
+ * create the framebuffer in the right opengl context. */
+ return MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
}
static void gpu_framebuffer_init(GPUFrameBuffer *fb)
{
- fb->object = GPU_fbo_alloc();
- fb->ctx = GPU_context_active_get();
- gpu_context_add_framebuffer(fb->ctx, fb);
+ fb->object = GPU_fbo_alloc();
+ fb->ctx = GPU_context_active_get();
+ gpu_context_add_framebuffer(fb->ctx, fb);
}
void GPU_framebuffer_free(GPUFrameBuffer *fb)
{
- for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; type++) {
- if (fb->attachments[type].tex != NULL) {
- GPU_framebuffer_texture_detach(fb, fb->attachments[type].tex);
- }
- }
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; type++) {
+ if (fb->attachments[type].tex != NULL) {
+ GPU_framebuffer_texture_detach(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);
- }
+ 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);
+ }
- if (GPU_framebuffer_active_get() == fb) {
- gpu_framebuffer_current_set(NULL);
- }
+ if (GPU_framebuffer_active_get() == fb) {
+ gpu_framebuffer_current_set(NULL);
+ }
- MEM_freeN(fb);
+ MEM_freeN(fb);
}
/* ---------- Attach ----------- */
-static void gpu_framebuffer_texture_attach_ex(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
+static void gpu_framebuffer_texture_attach_ex(
+ GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
{
- if (slot >= GPU_FB_MAX_COLOR_ATTACHMENT) {
- fprintf(stderr,
- "Attaching to index %d framebuffer slot unsupported. "
- "Use at most %d\n", slot, GPU_FB_MAX_COLOR_ATTACHMENT);
- return;
- }
+ if (slot >= GPU_FB_MAX_COLOR_ATTACHMENT) {
+ fprintf(stderr,
+ "Attaching to index %d framebuffer slot unsupported. "
+ "Use at most %d\n",
+ slot,
+ GPU_FB_MAX_COLOR_ATTACHMENT);
+ return;
+ }
- GPUAttachmentType type = attachment_type_from_tex(tex, slot);
- GPUAttachment *attachment = &fb->attachments[type];
+ GPUAttachmentType type = attachment_type_from_tex(tex, slot);
+ GPUAttachment *attachment = &fb->attachments[type];
- if ((attachment->tex == tex) &&
- (attachment->mip == mip) &&
- (attachment->layer == layer))
- {
- return; /* Exact same texture already bound here. */
- }
- else if (attachment->tex != NULL) {
- GPU_framebuffer_texture_detach(fb, attachment->tex);
- }
+ if ((attachment->tex == tex) && (attachment->mip == mip) && (attachment->layer == layer)) {
+ return; /* Exact same texture already bound here. */
+ }
+ else if (attachment->tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, attachment->tex);
+ }
- if (attachment->tex == NULL) {
- GPU_texture_attach_framebuffer(tex, fb, type);
- }
+ if (attachment->tex == NULL) {
+ GPU_texture_attach_framebuffer(tex, fb, type);
+ }
- attachment->tex = tex;
- attachment->mip = mip;
- attachment->layer = layer;
- GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
+ attachment->tex = tex;
+ attachment->mip = mip;
+ attachment->layer = layer;
+ GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
}
void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
{
- gpu_framebuffer_texture_attach_ex(fb, tex, slot, -1, mip);
+ 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)
+void GPU_framebuffer_texture_layer_attach(
+ GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
{
- /* 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);
+ /* 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)
+void GPU_framebuffer_texture_cubeface_attach(
+ GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip)
{
- BLI_assert(GPU_texture_cube(tex));
- gpu_framebuffer_texture_attach_ex(fb, tex, slot, face, mip);
+ 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)
{
- GPUAttachment *attachment = &fb->attachments[type];
+ GPUAttachment *attachment = &fb->attachments[type];
- if (attachment->tex != tex) {
- fprintf(stderr,
- "Warning, attempting to detach Texture %p from framebuffer %p "
- "but texture is not attached.\n", tex, fb);
- return;
- }
+ if (attachment->tex != tex) {
+ fprintf(stderr,
+ "Warning, attempting to detach Texture %p from framebuffer %p "
+ "but texture is not attached.\n",
+ tex,
+ fb);
+ return;
+ }
- attachment->tex = NULL;
- GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
+ attachment->tex = NULL;
+ GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
}
void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
{
- GPUAttachmentType type = GPU_texture_detach_framebuffer(tex, fb);
- GPU_framebuffer_texture_detach_slot(fb, tex, type);
+ GPUAttachmentType type = GPU_texture_detach_framebuffer(tex, fb);
+ GPU_framebuffer_texture_detach_slot(fb, tex, type);
}
/* ---------- Config (Attach & Detach) ----------- */
@@ -309,105 +310,109 @@ void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
*/
void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_len)
{
- 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);
- }
- else if (config[0].mip == -1) {
- /* 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);
- }
- else if (fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex != NULL) {
- GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex);
- }
-
- int slot = 0;
- for (int i = 1; i < config_len; ++i, ++slot) {
- if (config[i].tex != NULL) {
- BLI_assert(GPU_texture_depth(config[i].tex) == false);
- 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);
- if (tex != NULL) {
- GPU_framebuffer_texture_detach(fb, tex);
- }
- }
- }
+ 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);
+ }
+ else if (config[0].mip == -1) {
+ /* 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);
+ }
+ else if (fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex);
+ }
+
+ int slot = 0;
+ for (int i = 1; i < config_len; ++i, ++slot) {
+ if (config[i].tex != NULL) {
+ BLI_assert(GPU_texture_depth(config[i].tex) == false);
+ 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);
+ if (tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, tex);
+ }
+ }
+ }
}
/* ---------- Bind / Restore ----------- */
static void gpu_framebuffer_attachment_attach(GPUAttachment *attach, GPUAttachmentType attach_type)
{
- int tex_bind = GPU_texture_opengl_bindcode(attach->tex);
- GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
+ int tex_bind = GPU_texture_opengl_bindcode(attach->tex);
+ GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
- if (attach->layer > -1) {
- if (GPU_texture_cube(attach->tex)) {
- glFramebufferTexture2D(
- GL_FRAMEBUFFER, gl_attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X + attach->layer,
- tex_bind, attach->mip);
- }
- else {
- glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip, attach->layer);
- }
- }
- else {
- glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip);
- }
+ if (attach->layer > -1) {
+ if (GPU_texture_cube(attach->tex)) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER,
+ gl_attachment,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X + attach->layer,
+ tex_bind,
+ attach->mip);
+ }
+ else {
+ glFramebufferTextureLayer(
+ GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip, attach->layer);
+ }
+ }
+ else {
+ glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip);
+ }
}
-static void gpu_framebuffer_attachment_detach(GPUAttachment *UNUSED(attachment), GPUAttachmentType attach_type)
+static void gpu_framebuffer_attachment_detach(GPUAttachment *UNUSED(attachment),
+ GPUAttachmentType attach_type)
{
- GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
- glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, 0, 0);
+ GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
+ glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, 0, 0);
}
static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb)
{
- GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT];
- int numslots = 0;
-
- BLI_assert(GPU_framebuffer_active_get() == fb);
-
- /* Update attachments */
- for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
-
- if (type >= GPU_FB_COLOR_ATTACHMENT0) {
- if (fb->attachments[type].tex) {
- gl_attachments[numslots] = convert_attachment_type_to_gl(type);
- }
- else {
- gl_attachments[numslots] = GL_NONE;
- }
- numslots++;
- }
-
- if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type) == false) {
- continue;
- }
- else if (fb->attachments[type].tex != NULL) {
- gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
-
- fb->multisample = (GPU_texture_samples(fb->attachments[type].tex) > 0);
- fb->width = GPU_texture_width(fb->attachments[type].tex);
- fb->height = GPU_texture_height(fb->attachments[type].tex);
- }
- else {
- gpu_framebuffer_attachment_detach(&fb->attachments[type], type);
- }
- }
- fb->dirty_flag = 0;
-
- /* Update draw buffers (color targets)
- * This state is saved in the FBO */
- if (numslots)
- glDrawBuffers(numslots, gl_attachments);
- else
- glDrawBuffer(GL_NONE);
+ GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT];
+ int numslots = 0;
+
+ BLI_assert(GPU_framebuffer_active_get() == fb);
+
+ /* Update attachments */
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+
+ if (type >= GPU_FB_COLOR_ATTACHMENT0) {
+ if (fb->attachments[type].tex) {
+ gl_attachments[numslots] = convert_attachment_type_to_gl(type);
+ }
+ else {
+ gl_attachments[numslots] = GL_NONE;
+ }
+ numslots++;
+ }
+
+ if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type) == false) {
+ continue;
+ }
+ else if (fb->attachments[type].tex != NULL) {
+ gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
+
+ fb->multisample = (GPU_texture_samples(fb->attachments[type].tex) > 0);
+ fb->width = GPU_texture_width(fb->attachments[type].tex);
+ fb->height = GPU_texture_height(fb->attachments[type].tex);
+ }
+ else {
+ gpu_framebuffer_attachment_detach(&fb->attachments[type], type);
+ }
+ }
+ fb->dirty_flag = 0;
+
+ /* Update draw buffers (color targets)
+ * This state is saved in the FBO */
+ if (numslots)
+ glDrawBuffers(numslots, gl_attachments);
+ else
+ glDrawBuffer(GL_NONE);
}
/**
@@ -417,556 +422,564 @@ static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb)
*/
static void gpu_framebuffer_update_attachments_and_fill_empty_slots(GPUFrameBuffer *fb)
{
- GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT];
- int dummy_tex = 0;
-
- BLI_assert(GPU_framebuffer_active_get() == fb);
-
- /* Update attachments */
- for (GPUAttachmentType type = GPU_FB_MAX_ATTACHEMENT; type--;) {
- GPUTexture *tex = fb->attachments[type].tex;
-
- if (type >= GPU_FB_COLOR_ATTACHMENT0) {
- int slot = type - GPU_FB_COLOR_ATTACHMENT0;
- if (tex != NULL || (dummy_tex != 0)) {
- gl_attachments[slot] = convert_attachment_type_to_gl(type);
-
- if (dummy_tex == 0) {
- dummy_tex = GPU_texture_opengl_bindcode(tex);
- }
- }
- else {
- gl_attachments[slot] = GL_NONE;
- }
- }
- else {
- dummy_tex = 0;
- }
-
- if ((dummy_tex != 0) && tex == NULL) {
- /* Fill empty slot */
- glFramebufferTexture(GL_FRAMEBUFFER, convert_attachment_type_to_gl(type), dummy_tex, 0);
- }
- else if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type)) {
- if (tex != NULL) {
- gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
-
- fb->multisample = (GPU_texture_samples(tex) > 0);
- fb->width = GPU_texture_width(tex);
- fb->height = GPU_texture_height(tex);
- }
- else {
- gpu_framebuffer_attachment_detach(&fb->attachments[type], type);
- }
- }
- }
- fb->dirty_flag = 0;
-
- /* Update draw buffers (color targets)
- * This state is saved in the FBO */
- glDrawBuffers(GPU_FB_MAX_COLOR_ATTACHMENT, gl_attachments);
+ GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT];
+ int dummy_tex = 0;
+
+ BLI_assert(GPU_framebuffer_active_get() == fb);
+
+ /* Update attachments */
+ for (GPUAttachmentType type = GPU_FB_MAX_ATTACHEMENT; type--;) {
+ GPUTexture *tex = fb->attachments[type].tex;
+
+ if (type >= GPU_FB_COLOR_ATTACHMENT0) {
+ int slot = type - GPU_FB_COLOR_ATTACHMENT0;
+ if (tex != NULL || (dummy_tex != 0)) {
+ gl_attachments[slot] = convert_attachment_type_to_gl(type);
+
+ if (dummy_tex == 0) {
+ dummy_tex = GPU_texture_opengl_bindcode(tex);
+ }
+ }
+ else {
+ gl_attachments[slot] = GL_NONE;
+ }
+ }
+ else {
+ dummy_tex = 0;
+ }
+
+ if ((dummy_tex != 0) && tex == NULL) {
+ /* Fill empty slot */
+ glFramebufferTexture(GL_FRAMEBUFFER, convert_attachment_type_to_gl(type), dummy_tex, 0);
+ }
+ else if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type)) {
+ if (tex != NULL) {
+ gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
+
+ fb->multisample = (GPU_texture_samples(tex) > 0);
+ fb->width = GPU_texture_width(tex);
+ fb->height = GPU_texture_height(tex);
+ }
+ else {
+ gpu_framebuffer_attachment_detach(&fb->attachments[type], type);
+ }
+ }
+ }
+ fb->dirty_flag = 0;
+
+ /* Update draw buffers (color targets)
+ * This state is saved in the FBO */
+ glDrawBuffers(GPU_FB_MAX_COLOR_ATTACHMENT, gl_attachments);
}
-
#define FRAMEBUFFER_STACK_DEPTH 16
static struct {
- GPUFrameBuffer *framebuffers[FRAMEBUFFER_STACK_DEPTH];
- uint top;
+ GPUFrameBuffer *framebuffers[FRAMEBUFFER_STACK_DEPTH];
+ uint top;
} FrameBufferStack = {{0}};
static void gpuPushFrameBuffer(GPUFrameBuffer *fbo)
{
- BLI_assert(FrameBufferStack.top < FRAMEBUFFER_STACK_DEPTH);
- FrameBufferStack.framebuffers[FrameBufferStack.top] = fbo;
- FrameBufferStack.top++;
+ BLI_assert(FrameBufferStack.top < FRAMEBUFFER_STACK_DEPTH);
+ FrameBufferStack.framebuffers[FrameBufferStack.top] = fbo;
+ FrameBufferStack.top++;
}
static GPUFrameBuffer *gpuPopFrameBuffer(void)
{
- BLI_assert(FrameBufferStack.top > 0);
- FrameBufferStack.top--;
- return FrameBufferStack.framebuffers[FrameBufferStack.top];
+ BLI_assert(FrameBufferStack.top > 0);
+ FrameBufferStack.top--;
+ return FrameBufferStack.framebuffers[FrameBufferStack.top];
}
#undef FRAMEBUFFER_STACK_DEPTH
-
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
{
- if (fb->object == 0)
- gpu_framebuffer_init(fb);
+ if (fb->object == 0)
+ gpu_framebuffer_init(fb);
- if (GPU_framebuffer_active_get() != fb)
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ if (GPU_framebuffer_active_get() != fb)
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- gpu_framebuffer_current_set(fb);
+ gpu_framebuffer_current_set(fb);
- if (fb->dirty_flag != 0) {
- if (GPU_unused_fb_slot_workaround()) {
- /* XXX: Please AMD, fix this. */
- gpu_framebuffer_update_attachments_and_fill_empty_slots(fb);
- }
- else {
- gpu_framebuffer_update_attachments(fb);
- }
- }
+ if (fb->dirty_flag != 0) {
+ if (GPU_unused_fb_slot_workaround()) {
+ /* XXX: Please AMD, fix this. */
+ gpu_framebuffer_update_attachments_and_fill_empty_slots(fb);
+ }
+ else {
+ gpu_framebuffer_update_attachments(fb);
+ }
+ }
- /* TODO manually check for errors? */
+ /* TODO manually check for errors? */
#if 0
- char err_out[256];
- if (!GPU_framebuffer_check_valid(fb, err_out)) {
- printf("Invalid %s\n", err_out);
- }
+ char err_out[256];
+ if (!GPU_framebuffer_check_valid(fb, err_out)) {
+ printf("Invalid %s\n", err_out);
+ }
#endif
- if (fb->multisample)
- glEnable(GL_MULTISAMPLE);
+ if (fb->multisample)
+ glEnable(GL_MULTISAMPLE);
- glViewport(0, 0, fb->width, fb->height);
+ glViewport(0, 0, fb->width, fb->height);
}
void GPU_framebuffer_restore(void)
{
- if (GPU_framebuffer_active_get() != NULL) {
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- gpu_framebuffer_current_set(NULL);
- }
+ if (GPU_framebuffer_active_get() != NULL) {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ gpu_framebuffer_current_set(NULL);
+ }
}
bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
{
- return (fb == GPU_framebuffer_active_get()) && (fb->object != 0);
+ return (fb == GPU_framebuffer_active_get()) && (fb->object != 0);
}
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
{
- if (!GPU_framebuffer_bound(fb))
- GPU_framebuffer_bind(fb);
+ if (!GPU_framebuffer_bound(fb))
+ GPU_framebuffer_bind(fb);
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- GPU_framebuffer_restore();
- gpu_print_framebuffer_error(status, err_out);
- return false;
- }
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ GPU_framebuffer_restore();
+ gpu_print_framebuffer_error(status, err_out);
+ return false;
+ }
- return true;
+ return true;
}
/* ---------- Framebuffer Operations ----------- */
#define CHECK_FRAMEBUFFER_IS_BOUND(_fb) \
- BLI_assert(GPU_framebuffer_bound(_fb)); \
- UNUSED_VARS_NDEBUG(_fb);
+ BLI_assert(GPU_framebuffer_bound(_fb)); \
+ UNUSED_VARS_NDEBUG(_fb);
/* Needs to be done after binding. */
void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int w, int h)
{
- CHECK_FRAMEBUFFER_IS_BOUND(fb);
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
- glViewport(x, y, w, h);
+ glViewport(x, y, w, h);
}
-void GPU_framebuffer_clear(
- GPUFrameBuffer *fb, eGPUFrameBufferBits buffers,
- const float clear_col[4], float clear_depth, uint clear_stencil)
+void GPU_framebuffer_clear(GPUFrameBuffer *fb,
+ eGPUFrameBufferBits buffers,
+ const float clear_col[4],
+ float clear_depth,
+ uint clear_stencil)
{
- CHECK_FRAMEBUFFER_IS_BOUND(fb);
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
- if (buffers & GPU_COLOR_BIT) {
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]);
- }
- if (buffers & GPU_DEPTH_BIT) {
- glDepthMask(GL_TRUE);
- glClearDepth(clear_depth);
- }
- if (buffers & GPU_STENCIL_BIT) {
- glStencilMask(0xFF);
- glClearStencil(clear_stencil);
- }
+ if (buffers & GPU_COLOR_BIT) {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]);
+ }
+ if (buffers & GPU_DEPTH_BIT) {
+ glDepthMask(GL_TRUE);
+ glClearDepth(clear_depth);
+ }
+ if (buffers & GPU_STENCIL_BIT) {
+ glStencilMask(0xFF);
+ glClearStencil(clear_stencil);
+ }
- GLbitfield mask = convert_buffer_bits_to_gl(buffers);
- glClear(mask);
+ GLbitfield mask = convert_buffer_bits_to_gl(buffers);
+ glClear(mask);
}
void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data)
{
- CHECK_FRAMEBUFFER_IS_BOUND(fb);
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
- GLenum type = GL_DEPTH_COMPONENT;
- glReadBuffer(GL_COLOR_ATTACHMENT0); /* This is OK! */
- glReadPixels(x, y, w, h, type, GL_FLOAT, data);
+ GLenum type = GL_DEPTH_COMPONENT;
+ glReadBuffer(GL_COLOR_ATTACHMENT0); /* This is OK! */
+ glReadPixels(x, y, w, h, type, GL_FLOAT, data);
}
void GPU_framebuffer_read_color(
- GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data)
-{
- CHECK_FRAMEBUFFER_IS_BOUND(fb);
-
- GLenum type;
- switch (channels) {
- case 1: type = GL_RED; break;
- case 2: type = GL_RG; break;
- case 3: type = GL_RGB; break;
- case 4: type = GL_RGBA; break;
- default:
- BLI_assert(false && "wrong number of read channels");
- return;
- }
- glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
- glReadPixels(x, y, w, h, type, GL_FLOAT, data);
+ GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data)
+{
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
+
+ GLenum type;
+ switch (channels) {
+ case 1:
+ type = GL_RED;
+ break;
+ case 2:
+ type = GL_RG;
+ break;
+ case 3:
+ type = GL_RGB;
+ break;
+ case 4:
+ type = GL_RGBA;
+ break;
+ default:
+ BLI_assert(false && "wrong number of read channels");
+ return;
+ }
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
+ glReadPixels(x, y, w, h, type, GL_FLOAT, data);
}
/* read_slot and write_slot are only used for color buffers. */
-void GPU_framebuffer_blit(
- GPUFrameBuffer *fb_read, int read_slot,
- GPUFrameBuffer *fb_write, int write_slot,
- eGPUFrameBufferBits blit_buffers)
-{
- BLI_assert(blit_buffers != 0);
-
- GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
-
- /* 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);
- }
- if (fb_write->dirty_flag != 0 || fb_write->object == 0) {
- GPU_framebuffer_bind(fb_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));
-
- if (do_depth) {
- BLI_assert(GPU_texture_depth(read_tex) && GPU_texture_depth(write_tex));
- BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
- }
- if (do_stencil) {
- BLI_assert(GPU_texture_stencil(read_tex) && GPU_texture_stencil(write_tex));
- BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
- }
- if (GPU_texture_samples(write_tex) != 0 ||
- GPU_texture_samples(read_tex) != 0)
- {
- /* Can only blit multisample textures to another texture of the same size. */
- BLI_assert((fb_read->width == fb_write->width) &&
- (fb_read->height == fb_write->height));
- }
-
- glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object);
-
- if (do_color) {
- glReadBuffer(GL_COLOR_ATTACHMENT0 + read_slot);
- glDrawBuffer(GL_COLOR_ATTACHMENT0 + write_slot);
- /* XXX we messed with the glDrawBuffer, this will reset the
- * glDrawBuffers the next time we bind fb_write. */
- fb_write->dirty_flag = GPU_FB_DIRTY_DRAWBUFFER;
- }
-
- GLbitfield mask = convert_buffer_bits_to_gl(blit_buffers);
-
- glBlitFramebuffer(
- 0, 0, fb_read->width, fb_read->height,
- 0, 0, fb_write->width, fb_write->height,
- mask, GL_NEAREST);
-
- /* Restore previous framebuffer */
- if (fb_write == prev_fb) {
- GPU_framebuffer_bind(fb_write); /* To update drawbuffers */
- }
- else if (prev_fb) {
- glBindFramebuffer(GL_FRAMEBUFFER, prev_fb->object);
- gpu_framebuffer_current_set(prev_fb);
- }
- else {
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- gpu_framebuffer_current_set(NULL);
- }
+void GPU_framebuffer_blit(GPUFrameBuffer *fb_read,
+ int read_slot,
+ GPUFrameBuffer *fb_write,
+ int write_slot,
+ eGPUFrameBufferBits blit_buffers)
+{
+ BLI_assert(blit_buffers != 0);
+
+ GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get();
+
+ /* 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);
+ }
+ if (fb_write->dirty_flag != 0 || fb_write->object == 0) {
+ GPU_framebuffer_bind(fb_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));
+
+ if (do_depth) {
+ BLI_assert(GPU_texture_depth(read_tex) && GPU_texture_depth(write_tex));
+ BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
+ }
+ if (do_stencil) {
+ BLI_assert(GPU_texture_stencil(read_tex) && GPU_texture_stencil(write_tex));
+ BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
+ }
+ if (GPU_texture_samples(write_tex) != 0 || GPU_texture_samples(read_tex) != 0) {
+ /* Can only blit multisample textures to another texture of the same size. */
+ BLI_assert((fb_read->width == fb_write->width) && (fb_read->height == fb_write->height));
+ }
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object);
+
+ if (do_color) {
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + read_slot);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0 + write_slot);
+ /* XXX we messed with the glDrawBuffer, this will reset the
+ * glDrawBuffers the next time we bind fb_write. */
+ fb_write->dirty_flag = GPU_FB_DIRTY_DRAWBUFFER;
+ }
+
+ GLbitfield mask = convert_buffer_bits_to_gl(blit_buffers);
+
+ glBlitFramebuffer(0,
+ 0,
+ fb_read->width,
+ fb_read->height,
+ 0,
+ 0,
+ fb_write->width,
+ fb_write->height,
+ mask,
+ GL_NEAREST);
+
+ /* Restore previous framebuffer */
+ if (fb_write == prev_fb) {
+ GPU_framebuffer_bind(fb_write); /* To update drawbuffers */
+ }
+ else if (prev_fb) {
+ glBindFramebuffer(GL_FRAMEBUFFER, prev_fb->object);
+ gpu_framebuffer_current_set(prev_fb);
+ }
+ else {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ gpu_framebuffer_current_set(NULL);
+ }
}
/**
* Use this if you need to custom downsample your texture and use the previous mip level as 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, int max_lvl,
- void (*callback)(void *userData, int level), void *userData)
-{
- /* 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);
- }
- /* 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);
-
- int levels = floor(log2(max_ii(fb->width, fb->height)));
- max_lvl = min_ii(max_lvl, levels);
-
- int i;
- int current_dim[2] = {fb->width, fb->height};
- for (i = 1; i < max_lvl + 1; i++) {
- /* calculate next viewport size */
- current_dim[0] = max_ii(current_dim[0] / 2, 1);
- current_dim[1] = max_ii(current_dim[1] / 2, 1);
-
- for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
- if (fb->attachments[type].tex != NULL) {
- /* Some Intel HDXXX have issue with rendering to a mipmap that is below
- * the texture GL_TEXTURE_MAX_LEVEL. So even if it not correct, in this case
- * we allow GL_TEXTURE_MAX_LEVEL to be one level lower. In practice it does work! */
- int next_lvl = (GPU_mip_render_workaround()) ? i : i - 1;
- /* bind next level for rendering but first restrict fetches only to previous level */
- GPUTexture *tex = fb->attachments[type].tex;
- GPU_texture_bind(tex, 0);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, next_lvl);
- GPU_texture_unbind(tex);
- /* copy attachment and replace miplevel. */
- GPUAttachment attachment = fb->attachments[type];
- attachment.mip = i;
- gpu_framebuffer_attachment_attach(&attachment, type);
- }
- }
-
- BLI_assert(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));
-
- glViewport(0, 0, current_dim[0], current_dim[1]);
- callback(userData, i);
-
- if (current_dim[0] == 1 && current_dim[1] == 1)
- break;
- }
-
- for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
- if (fb->attachments[type].tex != NULL) {
- /* reset mipmap level range */
- GPUTexture *tex = fb->attachments[type].tex;
- GPU_texture_bind(tex, 0);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
- GPU_texture_unbind(tex);
- /* Reattach original level */
- /* NOTE: This is not necessary but this makes the FBO config
- * remain in sync with the GPUFrameBuffer config. */
- gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
- }
- }
-
- gpu_framebuffer_current_set(prev_fb);
+void GPU_framebuffer_recursive_downsample(GPUFrameBuffer *fb,
+ int max_lvl,
+ void (*callback)(void *userData, int level),
+ void *userData)
+{
+ /* 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);
+ }
+ /* 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);
+
+ int levels = floor(log2(max_ii(fb->width, fb->height)));
+ max_lvl = min_ii(max_lvl, levels);
+
+ int i;
+ int current_dim[2] = {fb->width, fb->height};
+ for (i = 1; i < max_lvl + 1; i++) {
+ /* calculate next viewport size */
+ current_dim[0] = max_ii(current_dim[0] / 2, 1);
+ current_dim[1] = max_ii(current_dim[1] / 2, 1);
+
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+ if (fb->attachments[type].tex != NULL) {
+ /* Some Intel HDXXX have issue with rendering to a mipmap that is below
+ * the texture GL_TEXTURE_MAX_LEVEL. So even if it not correct, in this case
+ * we allow GL_TEXTURE_MAX_LEVEL to be one level lower. In practice it does work! */
+ int next_lvl = (GPU_mip_render_workaround()) ? i : i - 1;
+ /* bind next level for rendering but first restrict fetches only to previous level */
+ GPUTexture *tex = fb->attachments[type].tex;
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, next_lvl);
+ GPU_texture_unbind(tex);
+ /* copy attachment and replace miplevel. */
+ GPUAttachment attachment = fb->attachments[type];
+ attachment.mip = i;
+ gpu_framebuffer_attachment_attach(&attachment, type);
+ }
+ }
+
+ BLI_assert(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ glViewport(0, 0, current_dim[0], current_dim[1]);
+ callback(userData, i);
+
+ if (current_dim[0] == 1 && current_dim[1] == 1)
+ break;
+ }
+
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+ if (fb->attachments[type].tex != NULL) {
+ /* reset mipmap level range */
+ GPUTexture *tex = fb->attachments[type].tex;
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
+ GPU_texture_unbind(tex);
+ /* Reattach original level */
+ /* NOTE: This is not necessary but this makes the FBO config
+ * remain in sync with the GPUFrameBuffer config. */
+ gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
+ }
+ }
+
+ gpu_framebuffer_current_set(prev_fb);
}
/* GPUOffScreen */
struct GPUOffScreen {
- GPUFrameBuffer *fb;
- GPUTexture *color;
- GPUTexture *depth;
+ GPUFrameBuffer *fb;
+ GPUTexture *color;
+ GPUTexture *depth;
};
-GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool depth, bool high_bitdepth, char err_out[256])
+GPUOffScreen *GPU_offscreen_create(
+ int width, int height, int samples, bool depth, bool high_bitdepth, char err_out[256])
{
- GPUOffScreen *ofs;
+ GPUOffScreen *ofs;
- ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
+ ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
- /* Sometimes areas can have 0 height or width and this will
- * create a 1D texture which we don't want. */
- height = max_ii(1, height);
- width = max_ii(1, width);
+ /* Sometimes areas can have 0 height or width and this will
+ * create a 1D texture which we don't want. */
+ height = max_ii(1, height);
+ width = max_ii(1, width);
- ofs->color = GPU_texture_create_2d_multisample(
- width, height,
- (high_bitdepth) ? GPU_RGBA16F : GPU_RGBA8, NULL, samples, err_out);
+ ofs->color = GPU_texture_create_2d_multisample(
+ width, height, (high_bitdepth) ? GPU_RGBA16F : GPU_RGBA8, NULL, samples, err_out);
- if (depth) {
- ofs->depth = GPU_texture_create_2d_multisample(width, height, GPU_DEPTH24_STENCIL8, NULL, samples, err_out);
- }
+ if (depth) {
+ ofs->depth = GPU_texture_create_2d_multisample(
+ width, height, GPU_DEPTH24_STENCIL8, NULL, samples, err_out);
+ }
- if ((depth && !ofs->depth) || !ofs->color) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
+ if ((depth && !ofs->depth) || !ofs->color) {
+ GPU_offscreen_free(ofs);
+ return NULL;
+ }
- gpuPushAttr(GPU_VIEWPORT_BIT);
+ gpuPushAttr(GPU_VIEWPORT_BIT);
- GPU_framebuffer_ensure_config(&ofs->fb, {
- GPU_ATTACHMENT_TEXTURE(ofs->depth),
- GPU_ATTACHMENT_TEXTURE(ofs->color)
- });
+ GPU_framebuffer_ensure_config(
+ &ofs->fb, {GPU_ATTACHMENT_TEXTURE(ofs->depth), GPU_ATTACHMENT_TEXTURE(ofs->color)});
- /* check validity at the very end! */
- if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
- GPU_offscreen_free(ofs);
- gpuPopAttr();
- return NULL;
- }
+ /* check validity at the very end! */
+ if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
+ GPU_offscreen_free(ofs);
+ gpuPopAttr();
+ return NULL;
+ }
- GPU_framebuffer_restore();
+ GPU_framebuffer_restore();
- gpuPopAttr();
+ gpuPopAttr();
- return ofs;
+ return ofs;
}
void GPU_offscreen_free(GPUOffScreen *ofs)
{
- if (ofs->fb)
- GPU_framebuffer_free(ofs->fb);
- if (ofs->color)
- GPU_texture_free(ofs->color);
- if (ofs->depth)
- GPU_texture_free(ofs->depth);
+ if (ofs->fb)
+ GPU_framebuffer_free(ofs->fb);
+ if (ofs->color)
+ GPU_texture_free(ofs->color);
+ if (ofs->depth)
+ GPU_texture_free(ofs->depth);
- MEM_freeN(ofs);
+ MEM_freeN(ofs);
}
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
{
- if (save) {
- gpuPushAttr(GPU_SCISSOR_BIT | GPU_VIEWPORT_BIT);
- GPUFrameBuffer *fb = GPU_framebuffer_active_get();
- gpuPushFrameBuffer(fb);
- }
- glDisable(GL_SCISSOR_TEST);
- GPU_framebuffer_bind(ofs->fb);
+ if (save) {
+ gpuPushAttr(GPU_SCISSOR_BIT | GPU_VIEWPORT_BIT);
+ GPUFrameBuffer *fb = GPU_framebuffer_active_get();
+ gpuPushFrameBuffer(fb);
+ }
+ glDisable(GL_SCISSOR_TEST);
+ GPU_framebuffer_bind(ofs->fb);
}
void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore)
{
- GPUFrameBuffer *fb = NULL;
+ GPUFrameBuffer *fb = NULL;
- if (restore) {
- gpuPopAttr();
- fb = gpuPopFrameBuffer();
- }
+ if (restore) {
+ gpuPopAttr();
+ fb = gpuPopFrameBuffer();
+ }
- if (fb) {
- GPU_framebuffer_bind(fb);
- }
- else {
- GPU_framebuffer_restore();
- }
+ if (fb) {
+ GPU_framebuffer_bind(fb);
+ }
+ else {
+ GPU_framebuffer_restore();
+ }
}
void GPU_offscreen_draw_to_screen(GPUOffScreen *ofs, int x, int y)
{
- const int w = GPU_texture_width(ofs->color);
- const int h = GPU_texture_height(ofs->color);
+ const int w = GPU_texture_width(ofs->color);
+ const int h = GPU_texture_height(ofs->color);
- glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->fb->object);
- GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->fb->object);
+ GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
- if (status == GL_FRAMEBUFFER_COMPLETE) {
- glBlitFramebuffer(0, 0, w, h, x, y, x + w, y + h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- }
- else {
- gpu_print_framebuffer_error(status, NULL);
- }
+ if (status == GL_FRAMEBUFFER_COMPLETE) {
+ glBlitFramebuffer(0, 0, w, h, x, y, x + w, y + h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ }
+ else {
+ gpu_print_framebuffer_error(status, NULL);
+ }
- glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
{
- const int w = GPU_texture_width(ofs->color);
- const int h = GPU_texture_height(ofs->color);
-
- BLI_assert(type == GL_UNSIGNED_BYTE || type == GL_FLOAT);
-
- if (GPU_texture_target(ofs->color) == GL_TEXTURE_2D_MULTISAMPLE) {
- /* For a multi-sample texture,
- * we need to create an intermediate buffer to blit to,
- * before its copied using 'glReadPixels' */
- GLuint fbo_blit = 0;
- GLuint tex_blit = 0;
-
- /* create texture for new 'fbo_blit' */
- glGenTextures(1, &tex_blit);
- glBindTexture(GL_TEXTURE_2D, tex_blit);
- glTexImage2D(
- GL_TEXTURE_2D, 0, (type == GL_FLOAT) ? GL_RGBA16F : GL_RGBA8,
- w, h, 0, GL_RGBA, type, 0);
-
- /* write into new single-sample buffer */
- glGenFramebuffers(1, &fbo_blit);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
- glFramebufferTexture2D(
- GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, tex_blit, 0);
-
- GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- goto finally;
- }
-
- /* perform the copy */
- glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
-
- /* read the results */
- glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_blit);
- glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
-
- /* restore the original frame-bufer */
- glBindFramebuffer(GL_FRAMEBUFFER, ofs->fb->object);
-
-finally:
- /* cleanup */
- glDeleteTextures(1, &tex_blit);
- glDeleteFramebuffers(1, &fbo_blit);
- }
- else {
- glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
- }
+ const int w = GPU_texture_width(ofs->color);
+ const int h = GPU_texture_height(ofs->color);
+
+ BLI_assert(type == GL_UNSIGNED_BYTE || type == GL_FLOAT);
+
+ if (GPU_texture_target(ofs->color) == GL_TEXTURE_2D_MULTISAMPLE) {
+ /* For a multi-sample texture,
+ * we need to create an intermediate buffer to blit to,
+ * before its copied using 'glReadPixels' */
+ GLuint fbo_blit = 0;
+ GLuint tex_blit = 0;
+
+ /* create texture for new 'fbo_blit' */
+ glGenTextures(1, &tex_blit);
+ glBindTexture(GL_TEXTURE_2D, tex_blit);
+ glTexImage2D(
+ GL_TEXTURE_2D, 0, (type == GL_FLOAT) ? GL_RGBA16F : GL_RGBA8, w, h, 0, GL_RGBA, type, 0);
+
+ /* write into new single-sample buffer */
+ glGenFramebuffers(1, &fbo_blit);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_blit, 0);
+
+ GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ goto finally;
+ }
+
+ /* perform the copy */
+ glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+ /* read the results */
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_blit);
+ glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
+
+ /* restore the original frame-bufer */
+ glBindFramebuffer(GL_FRAMEBUFFER, ofs->fb->object);
+
+ finally:
+ /* cleanup */
+ glDeleteTextures(1, &tex_blit);
+ glDeleteFramebuffers(1, &fbo_blit);
+ }
+ else {
+ glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
+ }
}
int GPU_offscreen_width(const GPUOffScreen *ofs)
{
- return GPU_texture_width(ofs->color);
+ return GPU_texture_width(ofs->color);
}
int GPU_offscreen_height(const GPUOffScreen *ofs)
{
- return GPU_texture_height(ofs->color);
+ return GPU_texture_height(ofs->color);
}
GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs)
{
- return ofs->color;
+ return ofs->color;
}
/* only to be used by viewport code! */
-void GPU_offscreen_viewport_data_get(
- GPUOffScreen *ofs,
- GPUFrameBuffer **r_fb, GPUTexture **r_color, GPUTexture **r_depth)
+void GPU_offscreen_viewport_data_get(GPUOffScreen *ofs,
+ GPUFrameBuffer **r_fb,
+ GPUTexture **r_color,
+ GPUTexture **r_depth)
{
- *r_fb = ofs->fb;
- *r_color = ofs->color;
- *r_depth = ofs->depth;
+ *r_fb = ofs->fb;
+ *r_color = ofs->color;
+ *r_depth = ofs->depth;
}
void GPU_clear_color(float red, float green, float blue, float alpha)
{
- glClearColor(red, green, blue, alpha);
+ glClearColor(red, green, blue, alpha);
}
void GPU_clear(eGPUFrameBufferBits flags)
{
- glClear(convert_buffer_bits_to_gl(flags));
+ glClear(convert_buffer_bits_to_gl(flags));
}