void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) { GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE; LLGLDepthTest depth(write_depth, write_depth); gGL.flush(); if (!source.mFBO || !mFBO) { llwarns << "Cannot copy framebuffer contents for non FBO render targets." << llendl; return; } if (mSampleBuffer) { mSampleBuffer->copyContents(source, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } else { if (mask == GL_DEPTH_BUFFER_BIT && !mStencil && source.mStencil != mStencil) { stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO); check_framebuffer_status(); gGL.getTexUnit(0)->bind(this, true); stop_glerror(); glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1); stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); } else { glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO); stop_glerror(); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO); stop_glerror(); check_framebuffer_status(); stop_glerror(); if(gGLManager.mIsATI && mask & GL_STENCIL_BUFFER_BIT) { mask &= ~GL_STENCIL_BUFFER_BIT; glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_STENCIL_BUFFER_BIT, filter); } if(mask) glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); stop_glerror(); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); stop_glerror(); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); } } }
//static void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) { if (!source.mFBO) { llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; } { GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE; LLGLDepthTest depth(write_depth, write_depth); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mSampleBuffer ? source.mSampleBuffer->mFBO : source.mFBO); stop_glerror(); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); stop_glerror(); check_framebuffer_status(); stop_glerror(); if(gGLManager.mIsATI && mask & GL_STENCIL_BUFFER_BIT) { mask &= ~GL_STENCIL_BUFFER_BIT; glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_STENCIL_BUFFER_BIT, filter); } if(mask) glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); stop_glerror(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); stop_glerror(); } }
void LLRenderTarget::bindTarget() { if (mFBO) { stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, mFBO); stop_glerror(); if (gGLManager.mHasDrawBuffers) { //setup multiple render targets GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3}; glDrawBuffersARB(mTex.size(), drawbuffers); } if (mTex.empty()) { //no color buffer to draw to glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); } check_framebuffer_status(); stop_glerror(); } glViewport(0, 0, mResX, mResY); sBoundTarget = this; }
void initOpenGl() { glewInit(); glEnable(GL_DEPTH_TEST); reload_shader(); //mesh and texture for pass 1 mesh_data = LoadMesh(mesh_name); texture_id = LoadTexture(texture_name.c_str()); //mesh for pass 2 (full screen quadrilateral) glGenVertexArrays(1, &quad_vao); glBindVertexArray(quad_vao); float vertices[] = {1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f}; //create vertex buffers for vertex coords glGenBuffers(1, &quad_vbo); glBindBuffer(GL_ARRAY_BUFFER, quad_vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); int pos_loc = glGetAttribLocation(shader_program, "pos_attrib"); if(pos_loc >= 0) { glEnableVertexAttribArray(pos_loc); glVertexAttribPointer(pos_loc, 3, GL_FLOAT, false, 0, 0); } //create texture to render pass 1 into const int w = glutGet(GLUT_WINDOW_WIDTH); const int h = glutGet(GLUT_WINDOW_HEIGHT); glGenTextures(1, &fbo_texture); glBindTexture(GL_TEXTURE_2D, fbo_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glBindTexture(GL_TEXTURE_2D, 0); //Create renderbuffer for depth. glGenRenderbuffers(1, &rbo_id); glBindRenderbuffer(GL_RENDERBUFFER, rbo_id); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h); //Create the framebuffer object glGenFramebuffers(1, &fbo_id); glBindFramebuffer(GL_FRAMEBUFFER, fbo_id); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_texture, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo_id); // attach depth renderbuffer check_framebuffer_status(); glBindFramebuffer(GL_FRAMEBUFFER, 0); }
void LLRenderTarget::addColorAttachment(U32 color_fmt) { if (color_fmt == 0) { return; } U32 offset = mTex.size(); if (offset >= 4 || (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) { llerrs << "Too many color attachments!" << llendl; } U32 tex; LLImageGL::generateTextures(1, &tex); gGL.getTexUnit(0)->bindManual(mUsage, tex); stop_glerror(); LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); stop_glerror(); if (offset == 0) { gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); } else { //don't filter data attachments gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } if (mUsage != LLTexUnit::TT_RECT_TEXTURE) { gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); } else { // ATI doesn't support mirrored repeat for rectangular textures. gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } if (mFBO) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset, LLTexUnit::getInternalType(mUsage), tex, 0); stop_glerror(); check_framebuffer_status(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } mTex.push_back(tex); }
bool test_framebuffertexture(GLenum textureType) { bool pass = true; GLuint fbo, texture; float expected[] = { 0, 1, 0 }; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); texture = create_bind_texture(textureType); /* Attach the texture to the framebuffer object */ glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0); if(!piglit_check_gl_error(GL_NO_ERROR) || !check_framebuffer_status(GL_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE)) { glDeleteFramebuffers(1, &fbo); glDeleteTextures(1, &texture); printf("Texture Type: %s. Error during setup.\n", piglit_get_gl_enum_name(textureType)); return false; } piglit_draw_rect(-1, -1, 2, 2); /* If the texture is a multisample texture, * convert it to a 2D texture */ if(textureType == GL_TEXTURE_2D_MULTISAMPLE || textureType == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { ConvertMultiSample2DToTexture2D(fbo); } /* Probe for the expected color value */ if(textureType == GL_TEXTURE_1D || textureType == GL_TEXTURE_1D_ARRAY) { if(!piglit_probe_rect_rgb(0, 0, 6, 1, expected)) { pass = false; } } else { if(!piglit_probe_rect_rgb(0, 0, 6, 6, expected)) { pass = false; } } /* Clean up */ glDeleteFramebuffers(1, &fbo); glDeleteTextures(1, &texture); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; return pass; }
/* Take a framebuffer object, that has a GL_TEXTURE_2D_MULTISAMPLE * or a layer of a GL_TEXTURE_2D_MULTISAMPLE_ARRAY attached to * color attachment 0. Then blit that framebuffer object to * a new fbo that has a GL_TEXTURE_2D attached. Finally * attach the new GL_TEXTURE_2D to the original fbo. */ void ConvertMultiSample2DToTexture2D(GLuint fboRead) { GLuint fboDraw, texture; glGenFramebuffers(1, &fboDraw); glGenTextures(1, &texture); glBindFramebuffer(GL_READ_FRAMEBUFFER, fboRead); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboDraw); texture = create_bind_texture(GL_TEXTURE_2D); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); if(!check_framebuffer_status(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE) || !check_framebuffer_status(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE)) { piglit_report_result(PIGLIT_FAIL); } glBlitFramebuffer(0, 0, 6, 6, 0, 0, 6, 6, GL_COLOR_BUFFER_BIT, GL_NEAREST); if(!piglit_check_gl_error(GL_NO_ERROR)) { glDeleteTextures(1, &texture); piglit_report_result(PIGLIT_FAIL); } glBindFramebuffer(GL_FRAMEBUFFER, fboRead); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); glDeleteFramebuffers(1, &fboDraw); if(!piglit_check_gl_error(GL_NO_ERROR)) { glDeleteTextures(1, &texture); piglit_report_result(PIGLIT_FAIL); } }
void GLFrameBuffer::onBind() { GLGraphicDevice& gd = *checked_cast<GLGraphicDevice*>(&Context::Instance().getGraphicFactory().getGraphicDevice()); gd.bindGLFrameBuffer(mFBO); if(mFBO != 0) { check_framebuffer_status(); std::vector<GLenum> buffers(mClearViews.size()); for(size_t i=0; i<mClearViews.size(); ++i) { buffers[i] = static_cast<GLenum>(i + GL_COLOR_ATTACHMENT0_EXT); } CHECK_GL_CALL(glDrawBuffers((GLsizei)buffers.size(), &buffers[0])); } else { GLenum targets[] = { GL_BACK_LEFT }; glDrawBuffers(1, &targets[0]); } }
void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) { if (!mFBO || !target.mFBO) { llerrs << "Cannot share depth buffer between non FBO render targets." << llendl; } if (target.mDepth) { llerrs << "Attempting to override existing depth buffer. Detach existing buffer first." << llendl; } if (target.mUseDepth) { llerrs << "Attempting to override existing shared depth buffer. Detach existing buffer first." << llendl; } if (mDepth) { stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO); stop_glerror(); if (mStencil) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth); stop_glerror(); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth); stop_glerror(); target.mStencil = true; } else { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0); stop_glerror(); } check_framebuffer_status(); glBindFramebuffer(GL_FRAMEBUFFER, 0); target.mUseDepth = true; } }
bool LLMultisampleBuffer::addColorAttachment(U32 color_fmt) { if (color_fmt == 0) { return true; } U32 offset = mTex.size(); if (offset >= 4 || (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) { llerrs << "Too many color attachments!" << llendl; } U32 tex; glGenRenderbuffers(1, &tex); glBindRenderbuffer(GL_RENDERBUFFER, tex); stop_glerror(); clear_glerror(); glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, color_fmt, mResX, mResY); if (glGetError() != GL_NO_ERROR) { llwarns << "Unable to allocate color buffer for multisample render target." << llendl; release(); return false; } sBytesAllocated += mResX*mResY*4; if (mFBO) { glBindFramebuffer(GL_FRAMEBUFFER, mFBO); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, GL_RENDERBUFFER, tex); check_framebuffer_status(); glBindFramebuffer(GL_FRAMEBUFFER, 0); } mTex.push_back(tex); return true; }
bool test_gl_layer(GLint prog, int layers, float *expected) { bool pass = true; GLuint fbo, texture; glGenFramebuffers(1, &fbo); glGenTextures(1, &texture); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glBindTexture(GL_TEXTURE_2D_ARRAY, texture); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 10, 10, 2, 0, GL_RGB, GL_FLOAT, NULL); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0); if(!check_framebuffer_status(GL_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE) || !piglit_check_gl_error(GL_NO_ERROR)) { piglit_report_result(PIGLIT_FAIL); } glClear(GL_COLOR_BUFFER_BIT); glUseProgram(prog); piglit_draw_rect(-1, -1, 2, 2); pass = probe_texture_layered_rgb(texture, 0, 0, 0, 10, 10, 2, expected) && pass; glDeleteTextures(1, &texture); glDeleteFramebuffers(1, &fbo); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; return pass; }
inline void print_current_framebuffer_status(){ // check FBO status GLenum status = check_framebuffer_status(GL_FRAMEBUFFER); switch(status) { case GL_FRAMEBUFFER_COMPLETE: //COUT << "complete" << std::std::endl; break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: std::cerr << "FBO: Attachment is NOT complete" << std::endl; break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: std::cerr << "FBO: Missing attachment" << std::endl; break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: std::cerr << "FBO: Incomplete draw buffer" << std::endl; break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: std::cerr << "FBO: Incomplete read buffer" << std::endl; break; #ifdef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: std::cerr << "FBO: Attached buffers have different dimensions" << std::endl; break; #endif case GL_FRAMEBUFFER_UNSUPPORTED: std::cerr << "FBO: Unsupported by implementation" << std::endl; break; default: std::cerr << "FBO: Unknown error: " << status << std::endl; break; } }
void LLRenderTarget::clear(U32 mask_in) { U32 mask = GL_COLOR_BUFFER_BIT; if (mUseDepth) { mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; } if (mFBO) { check_framebuffer_status(); stop_glerror(); glClear(mask & mask_in); stop_glerror(); } else { LLGLEnable scissor(GL_SCISSOR_TEST); glScissor(0, 0, mResX, mResY); stop_glerror(); glClear(mask & mask_in); } }
void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref) { if (!ref) { ref = this; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); if (gGLManager.mHasDrawBuffers) { //setup multiple render targets GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT}; glDrawBuffersARB(ref->mTex.size(), drawbuffers); } check_framebuffer_status(); glViewport(0, 0, mResX, mResY); sBoundTarget = this; }
//static void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) { if (!source.mFBO) { llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; } { GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE; LLGLDepthTest depth(write_depth, write_depth); glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO); stop_glerror(); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); stop_glerror(); check_framebuffer_status(); stop_glerror(); glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); } }
void LLRenderTarget::addColorAttachment(U32 color_fmt) { if (color_fmt == 0) { return; } U32 offset = mTex.size(); if (offset >= 4 || (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) { llerrs << "Too many color attachments!" << llendl; } U32 tex; LLImageGL::generateTextures(1, &tex); gGL.getTexUnit(0)->bindManual(mUsage, tex); stop_glerror(); #ifdef GL_ARB_texture_multisample if (mSamples > 1) { glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, color_fmt, mResX, mResY, GL_TRUE); } else #else llassert_always(mSamples <= 1); #endif { LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); } stop_glerror(); if (mSamples == 0) { if (offset == 0) { //use bilinear filtering on single texture render targets that aren't multisampled gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); stop_glerror(); } else { //don't filter data attachments gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); stop_glerror(); } if (mUsage != LLTexUnit::TT_RECT_TEXTURE) { gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); stop_glerror(); } else { // ATI doesn't support mirrored repeat for rectangular textures. gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); stop_glerror(); } } if (mFBO) { stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, mFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, LLTexUnit::getInternalType(mUsage), tex, 0); stop_glerror(); check_framebuffer_status(); glBindFramebuffer(GL_FRAMEBUFFER, 0); } mTex.push_back(tex); if (gDebugGL) { //bind and unbind to validate target bindTarget(); flush(); } }
void LLRenderTarget::flush(bool fetch_depth) { gGL.flush(); if (!mFBO) { gGL.getTexUnit(0)->bind(this); glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY); stop_glerror(); if (fetch_depth) { if (!mDepth) { allocateDepth(); } gGL.getTexUnit(0)->bind(this,true); glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY); stop_glerror(); //glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8, 0, 0, mResX, mResY, 0); } gGL.getTexUnit(0)->disable(); } else { stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); if (mSampleBuffer) { LLGLEnable multisample(GL_MULTISAMPLE); stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, mFBO); stop_glerror(); check_framebuffer_status(); glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleBuffer->mFBO); check_framebuffer_status(); stop_glerror(); if(gGLManager.mIsATI) { glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_STENCIL_BUFFER_BIT, GL_NEAREST); } else { glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); } stop_glerror(); //Following case never currently evalutes true, but it's still good to have. if (mTex.size() > 1) { for (U32 i = 1; i < mTex.size(); ++i) { glDrawBuffer(GL_COLOR_ATTACHMENT0 + i); glReadBuffer(GL_COLOR_ATTACHMENT0 + i); stop_glerror(); glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST); stop_glerror(); } /*for (U32 i = 1; i < mTex.size(); ++i) { glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, LLTexUnit::getInternalType(mUsage), mTex[i], 0); stop_glerror(); glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mSampleBuffer->mTex[i]); stop_glerror(); glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST); stop_glerror(); } for (U32 i = 0; i < mTex.size(); ++i) { glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, LLTexUnit::getInternalType(mUsage), mTex[i], 0); stop_glerror(); glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_RENDERBUFFER, mSampleBuffer->mTex[i]); stop_glerror(); }*/ } glBindFramebuffer(GL_FRAMEBUFFER, 0); } } }
void piglit_init(int argc, char **argv) { int j; bool pass = true; GLuint fbo, texture, program; static const float colors[6*3] = { 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0 }; program = piglit_build_simple_program_multiple_shaders( GL_VERTEX_SHADER, vs_source, GL_GEOMETRY_SHADER, gs_source, GL_FRAGMENT_SHADER, fs_source, 0); glUseProgram(program); /* Retrieve index from vs */ color_uniform = glGetUniformLocation(program, "color"); layer_uniform = glGetUniformLocation(program, "layer"); /* Gen textures */ glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); texture = create_bind_texture(); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0); if(!check_framebuffer_status(GL_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE) || !piglit_check_gl_error(GL_NO_ERROR)) { printf("Error with setup\n"); piglit_report_result(PIGLIT_FAIL); } /* draw quad on each layer with set color*/ glProvokingVertex(GL_LAST_VERTEX_CONVENTION); for(j = 0; j < 6; j++) { if (j == 3) { glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); } glUniform1i(layer_uniform, j); glUniform3fv(color_uniform, 1, &colors[j*3]); /* rect larger than vp */ piglit_draw_rect(-2, -2, 4, 4); } pass = probe_texture_layered_rgb(texture, 0, 0, 0, 6, 6, 6, colors) && pass; pass = piglit_check_gl_error(GL_NO_ERROR) && pass; /* Clean up */ glDeleteTextures(1, &texture); glDeleteFramebuffers(1, &fbo); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }
inline bool check_current_framebuffer_status(){ GLenum status = check_framebuffer_status(GL_FRAMEBUFFER); return (status == GL_FRAMEBUFFER_COMPLETE); }
void LLRenderTarget::flush(bool fetch_depth) { gGL.flush(); if (!mFBO) { gGL.getTexUnit(0)->bind(this); glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY); if (fetch_depth) { if (!mDepth) { allocateDepth(); } gGL.getTexUnit(0)->bind(this); glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0); } gGL.getTexUnit(0)->disable(); } else { stop_glerror(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); stop_glerror(); if (mSampleBuffer) { LLGLEnable multisample(GL_MULTISAMPLE_ARB); stop_glerror(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); stop_glerror(); check_framebuffer_status(); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mSampleBuffer->mFBO); check_framebuffer_status(); stop_glerror(); if(gGLManager.mIsATI) { glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_STENCIL_BUFFER_BIT, GL_NEAREST); } else glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); stop_glerror(); if (mTex.size() > 1) { for (U32 i = 1; i < mTex.size(); ++i) { glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, LLTexUnit::getInternalType(mUsage), mTex[i], 0); stop_glerror(); glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]); stop_glerror(); glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST); stop_glerror(); } for (U32 i = 0; i < mTex.size(); ++i) { glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, LLTexUnit::getInternalType(mUsage), mTex[i], 0); stop_glerror(); glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]); stop_glerror(); } } } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } }
bool LLRenderTarget::addColorAttachment(U32 color_fmt) { if (color_fmt == 0) { return true; } U32 offset = mTex.size(); if (offset >= 4 || (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) { llerrs << "Too many color attachments!" << llendl; } U32 tex; LLImageGL::generateTextures(1, &tex); gGL.getTexUnit(0)->bindManual(mUsage, tex); stop_glerror(); { clear_glerror(); LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); if (glGetError() != GL_NO_ERROR) { llwarns << "Could not allocate color buffer for render target." << llendl; return false; } } sBytesAllocated += mResX*mResY*4; stop_glerror(); if (offset == 0) { //use bilinear filtering on single texture render targets that aren't multisampled gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); stop_glerror(); } else { //don't filter data attachments gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); stop_glerror(); } if (mUsage != LLTexUnit::TT_RECT_TEXTURE) { gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); stop_glerror(); } else { // ATI doesn't support mirrored repeat for rectangular textures. gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); stop_glerror(); } if (mFBO) { stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, mFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, LLTexUnit::getInternalType(mUsage), tex, 0); stop_glerror(); check_framebuffer_status(); glBindFramebuffer(GL_FRAMEBUFFER, 0); } mTex.push_back(tex); if (gDebugGL) { //bind and unbind to validate target bindTarget(); flush(); } return true; }
bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples ) { release(); stop_glerror(); if (!gGLManager.mHasFramebufferMultisample || !gGLManager.mHasFramebufferObject || !(sUseFBO || use_fbo)) return false; if(color_fmt != GL_RGBA) { llwarns << "Unsupported color format: " << color_fmt << llendl; return false; } //Restrict to valid sample count { mSamples = samples; //mSamples = llmin(mSamples, (U32)4); //Cap to prevent memory bloat. mSamples = llmin(mSamples, (U32) gGLManager.mMaxSamples); } if (mSamples <= 1) return false; mResX = resx; mResY = resy; mUsage = usage; mUseDepth = depth; mStencil = stencil; mColorFormat = color_fmt; { if (depth) { stop_glerror(); if(!allocateDepth()) { release(); return false; } stop_glerror(); } glGenFramebuffers(1, (GLuint *) &mFBO); glBindFramebuffer(GL_FRAMEBUFFER, mFBO); stop_glerror(); clear_glerror(); if (mDepth) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth); if (mStencil) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth); } check_framebuffer_status(); } stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); } return addColorAttachment(color_fmt); }