void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex) { GLenum arbnumber; int number = GPU_texture_bound_number(tex); int bindcode = GPU_texture_opengl_bindcode(tex); int target = GPU_texture_target(tex); if (number >= GPU_max_textures()) { fprintf(stderr, "Not enough texture slots.\n"); return; } if (number == -1) return; if (location == -1) return; GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Texture"); arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number); if (number != 0) glActiveTexture(arbnumber); if (bindcode != 0) glBindTexture(target, bindcode); else GPU_invalid_tex_bind(target); glUniform1i(location, number); glEnable(target); if (number != 0) glActiveTexture(GL_TEXTURE0); GPU_ASSERT_NO_GL_ERRORS("Post Uniform Texture"); }
void GPU_framebuffer_texture_detach(GPUTexture *tex) { GLenum attachment; GPUFrameBuffer *fb = GPU_texture_framebuffer(tex); int fb_attachment = GPU_texture_framebuffer_attachment(tex); if (!fb) return; if (GG.currentfb != fb->object) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object); GG.currentfb = fb->object; } if (GPU_texture_depth(tex)) { fb->depthtex = NULL; attachment = GL_DEPTH_ATTACHMENT_EXT; } else { BLI_assert(fb->colortex[fb_attachment] == tex); fb->colortex[fb_attachment] = NULL; attachment = GL_COLOR_ATTACHMENT0_EXT + fb_attachment; } glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, GPU_texture_target(tex), 0, 0); GPU_texture_framebuffer_set(tex, NULL, -1); }
int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256]) { 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; } if ((G.debug & G_DEBUG)) { if (GPU_texture_bound_number(tex) != -1) { fprintf(stderr, "Feedback loop warning!: " "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n"); } } if (GPU_texture_depth(tex)) attachment = GL_DEPTH_ATTACHMENT_EXT; else attachment = GL_COLOR_ATTACHMENT0_EXT + slot; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 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 (error == GL_INVALID_OPERATION) { GPU_framebuffer_restore(); gpu_print_framebuffer_error(error, err_out); return 0; } if (GPU_texture_depth(tex)) fb->depthtex = tex; else fb->colortex[slot] = tex; GPU_texture_framebuffer_set(tex, fb, slot); return 1; }
static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen) { /* Setup offscreen color texture for drawing. */ GPUTexture *texture = GPU_offscreen_color_texture(offscreen); /* We don't support multisample textures here. */ BLI_assert(GPU_texture_target(texture) == GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); /* No mipmaps or filtering. */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); /* GL_TEXTURE_BASE_LEVEL = 0 by default */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glBindTexture(GL_TEXTURE_2D, 0); }
void GPU_texture_bind_as_framebuffer(GPUTexture *tex) { GPUFrameBuffer *fb = GPU_texture_framebuffer(tex); int fb_attachment = GPU_texture_framebuffer_attachment(tex); if (!fb) { fprintf(stderr, "Error, texture not bound to framebuffer!\n"); return; } /* push attributes */ glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT); glDisable(GL_SCISSOR_TEST); /* bind framebuffer */ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object); if (GPU_texture_depth(tex)) { glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); } 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); } if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) { glEnable(GL_MULTISAMPLE); } /* push matrices and set default viewport and matrix */ 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_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); 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' */ /* not needed since 'ofs' needs to be bound to the framebuffer already */ // #define USE_FBO_CTX_SWITCH GLuint fbo_blit = 0; GLuint tex_blit = 0; GLenum status; /* create texture for new 'fbo_blit' */ glGenTextures(1, &tex_blit); if (!tex_blit) { goto finally; } glBindTexture(GL_TEXTURE_2D, tex_blit); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, type, 0); #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, GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0); status = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { 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, GL_TEXTURE_2D, tex_blit, 0); status = glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { goto finally; } /* perform the copy */ glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST); /* read the results */ glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 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); #undef USE_FBO_CTX_SWITCH #endif finally: /* cleanup */ if (tex_blit) { glDeleteTextures(1, &tex_blit); } if (fbo_blit) { glDeleteFramebuffersEXT(1, &fbo_blit); } GPU_ASSERT_NO_GL_ERRORS("Read Multi-Sample Pixels"); } else { glReadPixels(0, 0, w, h, GL_RGBA, type, pixels); } }