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:
Diffstat (limited to 'source/blender/gpu/intern/gpu_framebuffer.c')
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c405
1 files changed, 226 insertions, 179 deletions
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index e7a8beae5cc..52e9a6aec3a 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -32,9 +32,10 @@
#include "BKE_global.h"
-#include "GPU_debug.h"
-#include "GPU_glew.h"
+#include "GPU_batch.h"
+#include "GPU_draw.h"
#include "GPU_framebuffer.h"
+#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -50,48 +51,42 @@ struct GPUFrameBuffer {
GLuint object;
GPUTexture *colortex[GPU_FB_MAX_SLOTS];
GPUTexture *depthtex;
+ struct GPUStateValues attribs;
};
static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
{
+ 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) {
- case GL_FRAMEBUFFER_COMPLETE_EXT:
- break;
- case GL_INVALID_OPERATION:
- err = "Invalid operation";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
- err = "Incomplete attachment";
- break;
- case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
- err = "Unsupported framebuffer format";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
- err = "Missing attachment";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
- err = "Attached images must have same dimensions";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
- err = "Attached images must have same format";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
- err = "Missing draw buffer";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
- err = "Missing read buffer";
- break;
+ /* 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)
+#else /* for desktop GL only */
+ 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, "GPUFrameBuffer: framebuffer incomplete error %d '%s'",
- (int)status, err);
+ BLI_snprintf(err_out, 256, format, err);
}
else {
- fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d '%s'\n",
- (int)status, err);
+ fprintf(stderr, format, err);
}
}
@@ -101,41 +96,33 @@ GPUFrameBuffer *GPU_framebuffer_create(void)
{
GPUFrameBuffer *fb;
- if (!(GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object ||
- (GLEW_EXT_framebuffer_object && GLEW_EXT_framebuffer_blit)))
- {
- return NULL;
- }
-
fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
- glGenFramebuffersEXT(1, &fb->object);
+ glGenFramebuffers(1, &fb->object);
if (!fb->object) {
- fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n",
- (int)glGetError());
+ fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed.\n");
GPU_framebuffer_free(fb);
return NULL;
}
/* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
glReadBuffer(GL_NONE);
glDrawBuffer(GL_NONE);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
return fb;
}
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
+bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
{
GLenum attachment;
- GLenum error;
if (slot >= GPU_FB_MAX_SLOTS) {
fprintf(stderr,
"Attaching to index %d framebuffer slot unsupported. "
"Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
- return 0;
+ return false;
}
if ((G.debug & G_DEBUG)) {
@@ -146,27 +133,26 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot
}
}
- if (GPU_texture_depth(tex))
- attachment = GL_DEPTH_ATTACHMENT_EXT;
- else
- attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
GG.currentfb = fb->object;
- /* Clean glError buffer. */
- while (glGetError() != GL_NO_ERROR) {}
-
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
- GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), 0);
-
- error = glGetError();
+ if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
+ attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ else if (GPU_texture_depth(tex))
+ attachment = GL_DEPTH_ATTACHMENT;
+ else
+ attachment = GL_COLOR_ATTACHMENT0 + slot;
- if (error == GL_INVALID_OPERATION) {
- GPU_framebuffer_restore();
- gpu_print_framebuffer_error(error, err_out);
- return 0;
- }
+#if defined(WITH_GL_PROFILE_COMPAT)
+ /* Workaround for Mac & Mesa compatibility profile, remove after we switch to core profile */
+ /* glFramebufferTexture was introduced in 3.2. It is *not* available in the ARB FBO extension */
+ if (GLEW_VERSION_3_2)
+ glFramebufferTexture(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), mip); /* normal core call, same as below */
+ else
+ glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), mip);
+#else
+ glFramebufferTexture(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), mip);
+#endif
if (GPU_texture_depth(tex))
fb->depthtex = tex;
@@ -175,7 +161,7 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot
GPU_texture_framebuffer_set(tex, fb, slot);
- return 1;
+ return true;
}
void GPU_framebuffer_texture_detach(GPUTexture *tex)
@@ -188,21 +174,34 @@ void GPU_framebuffer_texture_detach(GPUTexture *tex)
return;
if (GG.currentfb != fb->object) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
GG.currentfb = fb->object;
}
- if (GPU_texture_depth(tex)) {
+ if (GPU_texture_stencil(tex) && GPU_texture_depth(tex)) {
+ fb->depthtex = NULL;
+ attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ }
+ else if (GPU_texture_depth(tex)) {
fb->depthtex = NULL;
- attachment = GL_DEPTH_ATTACHMENT_EXT;
+ attachment = GL_DEPTH_ATTACHMENT;
}
else {
BLI_assert(fb->colortex[fb_attachment] == tex);
fb->colortex[fb_attachment] = NULL;
- attachment = GL_COLOR_ATTACHMENT0_EXT + fb_attachment;
+ attachment = GL_COLOR_ATTACHMENT0 + fb_attachment;
}
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, GPU_texture_target(tex), 0, 0);
+#if defined(WITH_GL_PROFILE_COMPAT)
+ /* Workaround for Mac & Mesa compatibility profile, remove after we switch to core profile */
+ /* glFramebufferTexture was introduced in 3.2. It is *not* available in the ARB FBO extension */
+ if (GLEW_VERSION_3_2)
+ glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0); /* normal core call, same as below */
+ else
+ glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GPU_texture_target(tex), 0, 0);
+#else
+ glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0);
+#endif
GPU_texture_framebuffer_set(tex, NULL, -1);
}
@@ -218,11 +217,11 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
}
/* push attributes */
- glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
+ gpuSaveState(&fb->attribs, GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
glDisable(GL_SCISSOR_TEST);
/* bind framebuffer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
if (GPU_texture_depth(tex)) {
glDrawBuffer(GL_NONE);
@@ -230,22 +229,17 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
}
else {
/* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + fb_attachment);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + fb_attachment);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0 + fb_attachment);
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + fb_attachment);
}
if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) {
glEnable(GL_MULTISAMPLE);
}
- /* push matrices and set default viewport and matrix */
+ /* set default viewport */
glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
GG.currentfb = fb->object;
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
}
void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
@@ -260,56 +254,81 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
for (i = 0; i < 4; i++) {
if (fb->colortex[i]) {
- attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
+ attachments[numslots] = GL_COLOR_ATTACHMENT0 + i;
numslots++;
}
}
/* push attributes */
- glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
+ gpuSaveState(&fb->attribs, GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
glDisable(GL_SCISSOR_TEST);
/* bind framebuffer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
/* last bound prevails here, better allow explicit control here too */
glDrawBuffers(numslots, attachments);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
- /* push matrices and set default viewport and matrix */
+ /* set default viewport */
glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
GG.currentfb = fb->object;
+}
+
+void GPU_framebuffer_bind(GPUFrameBuffer *fb)
+{
+ int numslots = 0, i;
+ GLenum attachments[4];
+ GLenum readattachement = 0;
+ GPUTexture *tex;
+
+ for (i = 0; i < 4; i++) {
+ if (fb->colortex[i]) {
+ attachments[numslots] = GL_COLOR_ATTACHMENT0 + i;
+ tex = fb->colortex[i];
+
+ if (!readattachement)
+ readattachement = GL_COLOR_ATTACHMENT0 + i;
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ numslots++;
+ }
+ }
+
+ /* bind framebuffer */
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+
+ if (numslots == 0) {
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+ tex = fb->depthtex;
+ }
+ else {
+ /* last bound prevails here, better allow explicit control here too */
+ glDrawBuffers(numslots, attachments);
+ glReadBuffer(readattachement);
+ }
+
+ glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
+ GG.currentfb = fb->object;
}
-void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
+void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *UNUSED(tex))
{
- /* restore matrix */
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
/* restore attributes */
- glPopAttrib();
+ gpuRestoreState(&fb->attribs);
}
void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
{
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
/* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0 + slot);
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
/* push matrices and set default viewport and matrix */
glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
GG.currentfb = fb->object;
- GG.currentfb = fb->object;
}
bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
@@ -319,22 +338,17 @@ bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
{
- GLenum status;
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
GG.currentfb = fb->object;
-
- /* Clean glError buffer. */
- while (glGetError() != GL_NO_ERROR) {}
-
- status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
GPU_framebuffer_restore();
gpu_print_framebuffer_error(status, err_out);
return false;
}
-
+
return true;
}
@@ -351,10 +365,10 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb)
}
if (fb->object) {
- glDeleteFramebuffersEXT(1, &fb->object);
+ glDeleteFramebuffers(1, &fb->object);
if (GG.currentfb == fb->object) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
GG.currentfb = 0;
}
}
@@ -365,7 +379,7 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb)
void GPU_framebuffer_restore(void)
{
if (GG.currentfb != 0) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
GG.currentfb = 0;
}
}
@@ -374,73 +388,113 @@ void GPU_framebuffer_blur(
GPUFrameBuffer *fb, GPUTexture *tex,
GPUFrameBuffer *blurfb, GPUTexture *blurtex)
{
+ const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
+ const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
+
+ static VertexFormat format = {0};
+ static VertexBuffer vbo = {{0}};
+ static Batch batch = {{0}};
+
const float scaleh[2] = {1.0f / GPU_texture_width(blurtex), 0.0f};
const float scalev[2] = {0.0f, 1.0f / GPU_texture_height(tex)};
GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
- int scale_uniform, texture_source_uniform;
if (!blur_shader)
return;
- scale_uniform = GPU_shader_get_uniform(blur_shader, "ScaleU");
- texture_source_uniform = GPU_shader_get_uniform(blur_shader, "textureSource");
+ /* Preparing to draw quad */
+ if (format.attrib_ct == 0) {
+ unsigned int i = 0;
+ /* Vertex format */
+ unsigned int pos = VertexFormat_add_attrib(&format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned int uvs = VertexFormat_add_attrib(&format, "uvs", COMP_F32, 2, KEEP_FLOAT);
+
+ /* Vertices */
+ VertexBuffer_init_with_format(&vbo, &format);
+ VertexBuffer_allocate_data(&vbo, 36);
+
+ for (int j = 0; j < 3; ++j) {
+ VertexBuffer_set_attrib(&vbo, uvs, i, fullscreenuvs[j]);
+ VertexBuffer_set_attrib(&vbo, pos, i++, fullscreencos[j]);
+ }
+ for (int j = 1; j < 4; ++j) {
+ VertexBuffer_set_attrib(&vbo, uvs, i, fullscreenuvs[j]);
+ VertexBuffer_set_attrib(&vbo, pos, i++, fullscreencos[j]);
+ }
+
+ Batch_init(&batch, GL_TRIANGLES, &vbo, NULL);
+ }
+ glDisable(GL_DEPTH_TEST);
+
/* Blurring horizontally */
-
/* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
* pushing unnecessary matrices onto the OpenGL stack. */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glBindFramebuffer(GL_FRAMEBUFFER, blurfb->object);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
/* avoid warnings from texture binding */
GG.currentfb = blurfb->object;
- GPU_shader_bind(blur_shader);
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
- GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
glViewport(0, 0, GPU_texture_width(blurtex), GPU_texture_height(blurtex));
- /* Preparing to draw quad */
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glDisable(GL_DEPTH_TEST);
-
GPU_texture_bind(tex, 0);
- /* Drawing quad */
- glBegin(GL_QUADS);
- glTexCoord2d(0, 0); glVertex2f(1, 1);
- glTexCoord2d(1, 0); glVertex2f(-1, 1);
- glTexCoord2d(1, 1); glVertex2f(-1, -1);
- glTexCoord2d(0, 1); glVertex2f(1, -1);
- glEnd();
+ Batch_set_builtin_program(&batch, GPU_SHADER_SEP_GAUSSIAN_BLUR);
+ Batch_Uniform2f(&batch, "ScaleU", scaleh[0], scaleh[1]);
+ Batch_Uniform1i(&batch, "textureSource", GL_TEXTURE0);
+ Batch_draw(&batch);
/* Blurring vertically */
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
GG.currentfb = fb->object;
glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
- GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
+
GPU_texture_bind(blurtex, 0);
- glBegin(GL_QUADS);
- glTexCoord2d(0, 0); glVertex2f(1, 1);
- glTexCoord2d(1, 0); glVertex2f(-1, 1);
- glTexCoord2d(1, 1); glVertex2f(-1, -1);
- glTexCoord2d(0, 1); glVertex2f(1, -1);
- glEnd();
+ /* Hack to make the following uniform stick */
+ Batch_set_builtin_program(&batch, GPU_SHADER_SEP_GAUSSIAN_BLUR);
+ Batch_Uniform2f(&batch, "ScaleU", scalev[0], scalev[1]);
+ Batch_Uniform1i(&batch, "textureSource", GL_TEXTURE0);
+ Batch_draw(&batch);
+}
- GPU_shader_unbind();
+void GPU_framebuffer_blit(GPUFrameBuffer *fb_read, int read_slot, GPUFrameBuffer *fb_write, int write_slot, bool use_depth)
+{
+ GPUTexture *read_tex = (use_depth) ? fb_read->depthtex : fb_read->colortex[read_slot];
+ GPUTexture *write_tex = (use_depth) ? fb_write->depthtex : fb_write->colortex[write_slot];
+ int read_attach = (use_depth) ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(read_tex);
+ int write_attach = (use_depth) ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(write_tex);
+ int read_bind = GPU_texture_opengl_bindcode(read_tex);
+ int write_bind = GPU_texture_opengl_bindcode(write_tex);
+ const int read_w = GPU_texture_width(read_tex);
+ const int read_h = GPU_texture_height(read_tex);
+ const int write_w = GPU_texture_width(write_tex);
+ const int write_h = GPU_texture_height(write_tex);
+
+ /* read from multi-sample buffer */
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object);
+ glFramebufferTexture2D(
+ GL_READ_FRAMEBUFFER, read_attach,
+ GL_TEXTURE_2D, read_bind, 0);
+ BLI_assert(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+ /* write into new single-sample buffer */
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object);
+ glFramebufferTexture2D(
+ GL_DRAW_FRAMEBUFFER, write_attach,
+ GL_TEXTURE_2D, write_bind, 0);
+ BLI_assert(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+ glBlitFramebuffer(0, 0, read_w, read_h, 0, 0, write_w, write_h, (use_depth) ? GL_DEPTH_BUFFER_BIT : GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+ /* Restore previous framebuffer */
+ glBindFramebuffer(GL_FRAMEBUFFER, GG.currentfb);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
}
/* GPUOffScreen */
@@ -464,12 +518,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_
}
if (samples) {
- if (!GLEW_EXT_framebuffer_multisample ||
- !GLEW_ARB_texture_multisample ||
- /* Only needed for GPU_offscreen_read_pixels.
- * We could add an arg if we intend to use multi-sample
- * offscreen buffers w/o reading their pixels */
- !GLEW_EXT_framebuffer_blit ||
+ if (!GLEW_ARB_texture_multisample ||
/* This is required when blitting from a multi-sampled buffers,
* even though we're not scaling. */
!GLEW_EXT_framebuffer_multisample_blit_scaled)
@@ -484,18 +533,18 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_
return NULL;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, 0)) {
GPU_offscreen_free(ofs);
return NULL;
}
- ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, GPU_HDR_NONE, samples, err_out);
+ ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, samples, err_out);
if (!ofs->color) {
GPU_offscreen_free(ofs);
return NULL;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, 0)) {
GPU_offscreen_free(ofs);
return NULL;
}
@@ -569,37 +618,37 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
#ifdef USE_FBO_CTX_SWITCH
/* read from multi-sample buffer */
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, ofs->color->fb->object);
- glFramebufferTexture2DEXT(
- GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + ofs->color->fb_attachment,
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->color->fb->object);
+ glFramebufferTexture2D(
+ GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + ofs->color->fb_attachment,
GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
- status = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER_EXT);
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
goto finally;
}
#endif
/* write into new single-sample buffer */
- glGenFramebuffersEXT(1, &fbo_blit);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo_blit);
- glFramebufferTexture2DEXT(
- GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ glGenFramebuffers(1, &fbo_blit);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
+ glFramebufferTexture2D(
+ GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, tex_blit, 0);
- status = glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT);
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
goto finally;
}
/* perform the copy */
- glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
/* read the results */
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fbo_blit);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_blit);
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
#ifdef USE_FBO_CTX_SWITCH
/* restore the original frame-bufer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ofs->color->fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, ofs->color->fb->object);
#undef USE_FBO_CTX_SWITCH
#endif
@@ -610,10 +659,8 @@ finally:
glDeleteTextures(1, &tex_blit);
}
if (fbo_blit) {
- glDeleteFramebuffersEXT(1, &fbo_blit);
+ glDeleteFramebuffers(1, &fbo_blit);
}
-
- GPU_ASSERT_NO_GL_ERRORS("Read Multi-Sample Pixels");
}
else {
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);