void piglit_init(int argc, char **argv) { GLint max_samples, rb_samples; GLuint rb, list; GLint width; bool pass = true; piglit_require_extension("GL_EXT_framebuffer_multisample"); glGetIntegerv(GL_MAX_SAMPLES, &max_samples); if (!piglit_check_gl_error(0)) piglit_report_result(PIGLIT_FAIL); glGenRenderbuffersEXT(1, &rb); glBindRenderbufferEXT(GL_RENDERBUFFER, rb); /* Make the list. The Storage should be called during compile. */ list = glGenLists(1); glNewList(list, GL_COMPILE); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, max_samples, GL_RGBA, 1, 1); glEndList(); /* Make sure that the command occurred during the compile. */ glGetRenderbufferParameterivEXT(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &rb_samples); if (rb_samples != max_samples) { fprintf(stderr, "glRenderbufferStorageMultisampleEXT not called during " "display list compile\n"); pass = false; } /* Now, make sure that it doesn't occur at execute. Start * with storage of a different size so we can distinguish. */ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, max_samples, GL_RGBA, 2, 2); glCallList(list); glGetRenderbufferParameterivEXT(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width); if (width != 2) { fprintf(stderr, "glRenderbufferStorageMultisampleEXT called " "during display list execute"); pass = false; } glDeleteRenderbuffersEXT(1, &rb); piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }
void LLMultisampleBuffer::allocateDepth() { glGenRenderbuffersEXT(1, (GLuint* ) &mDepth); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth); if (mStencil) { glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH24_STENCIL8_EXT, mResX, mResY); } else { glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH_COMPONENT16_ARB, mResX, mResY); } }
Renderbuffer::Obj::Obj( int aWidth, int aHeight, GLenum internalFormat, int msaaSamples, int coverageSamples ) : mWidth( aWidth ), mHeight( aHeight ), mInternalFormat( internalFormat ), mSamples( msaaSamples ), mCoverageSamples( coverageSamples ) { #if defined( CINDER_MSW ) static bool csaaSupported = ( GLEE_NV_framebuffer_multisample_coverage != 0 ); #else static bool csaaSupported = false; #endif GL_SUFFIX(glGenRenderbuffers)( 1, &mId ); if( mSamples > Fbo::getMaxSamples() ) mSamples = Fbo::getMaxSamples(); if( ! csaaSupported ) mCoverageSamples = 0; GL_SUFFIX(glBindRenderbuffer)( GL_SUFFIX(GL_RENDERBUFFER_), mId ); #if ! defined( CINDER_GLES ) #if defined( CINDER_MSW ) if( mCoverageSamples ) // create a CSAA buffer glRenderbufferStorageMultisampleCoverageNV( GL_RENDERBUFFER_EXT, mCoverageSamples, mSamples, mInternalFormat, mWidth, mHeight ); else #endif if( mSamples ) // create a regular MSAA buffer glRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, mSamples, mInternalFormat, mWidth, mHeight ); else #endif GL_SUFFIX(glRenderbufferStorage)( GL_SUFFIX(GL_RENDERBUFFER_), mInternalFormat, mWidth, mHeight ); }
bool RenderSurface::CreateRenderBuffer(unsigned width, unsigned height, unsigned format, int multiSample) { Graphics* graphics = parentTexture_->GetGraphics(); if (!graphics) return false; Release(); #ifndef GL_ES_VERSION_2_0 if (Graphics::GetGL3Support()) { glGenRenderbuffers(1, &renderBuffer_); glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer_); if (multiSample > 1) glRenderbufferStorageMultisample(GL_RENDERBUFFER, multiSample, format, width, height); else glRenderbufferStorage(GL_RENDERBUFFER, format, width, height); glBindRenderbuffer(GL_RENDERBUFFER, 0); } else #endif { glGenRenderbuffersEXT(1, &renderBuffer_); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderBuffer_); #ifndef GL_ES_VERSION_2_0 if (multiSample > 1) glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, multiSample, format, width, height); else #endif glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, width, height); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); } return true; }
void GL_GenerateFBO(GLuint texId, GLuint *fboId, int w, int h) { GLuint cRboId; Console_Printf(" Generate FBO %dx%d. ", w, h); glGenFramebuffersEXT(1, fboId); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, *fboId); if(vid_multisample.integer && gl_ext_framebuffer_multisample.integer) { Console_Printf("(MSAA) "); glGenRenderbuffersEXT(1, &cRboId); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, cRboId); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, vid_multisample.integer, GL_RGBA, w, h); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, cRboId); } glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texId, 0); //glDrawBuffer(GL_FRONT); //glReadBuffer(GL_FRONT); GL_CheckFBOStatus(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); }
void piglit_init(int argc, char **argv) { GLint max_samples; GLuint rb; piglit_require_extension("GL_EXT_framebuffer_multisample"); if (piglit_is_extension_supported("GL_ARB_internalformat_query")) { printf("ARB_internalformat_query is supported and " "redefines this behavior; skipping\n"); piglit_report_result(PIGLIT_SKIP); } if (piglit_is_extension_supported("GL_ARB_texture_multisample")) { printf("ARB_texture_multisample is supposed and " "redefines this behavior; skipping\n"); piglit_report_result(PIGLIT_SKIP); } glGetIntegerv(GL_MAX_SAMPLES, &max_samples); glGenRenderbuffersEXT(1, &rb); glBindRenderbufferEXT(GL_RENDERBUFFER, rb); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, max_samples + 1, GL_RGBA, 1, 1); if (!piglit_check_gl_error(GL_INVALID_VALUE)) piglit_report_result(PIGLIT_FAIL); glDeleteRenderbuffersEXT(1, &rb); piglit_report_result(PIGLIT_PASS); }
inline void VL_glRenderbufferStorageMultisample( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height ) { if (glRenderbufferStorageMultisample) glRenderbufferStorageMultisample(target, samples, internalformat, width, height); else if (glRenderbufferStorageMultisampleEXT) glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height); else VL_UNSUPPORTED_FUNC(); }
void display_reset(int samples, bool vsync) { int interval = vsync ? 1 : 0; if (enigma::is_ext_swapcontrol_supported()) { wglSwapIntervalEXT(interval); } GLint fbo; glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fbo); GLuint ColorBufferID, DepthBufferID; // Cleanup the multi-sampler fbo if turning off multi-sampling if (samples == 0) { if (enigma::msaa_fbo != 0) { glDeleteFramebuffers(1, &enigma::msaa_fbo); enigma::msaa_fbo = 0; } return; } //TODO: Change the code below to fix this to size properly to views // If we don't already have a multi-sample fbo then create one if (enigma::msaa_fbo == 0) { glGenFramebuffersEXT(1, &enigma::msaa_fbo); } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, enigma::msaa_fbo); // Now make a multi-sample color buffer glGenRenderbuffersEXT(1, &ColorBufferID); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ColorBufferID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_RGBA8, window_get_region_width_scaled(), window_get_region_height_scaled()); // We also need a depth buffer glGenRenderbuffersEXT(1, &DepthBufferID); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthBufferID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH_COMPONENT24, window_get_region_width_scaled(), window_get_region_height_scaled()); // Attach the render buffers to the multi-sampler fbo glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, ColorBufferID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, DepthBufferID); }
void RenderBuffer::init(const QSize& size, uint internal_format, int numSamp) { if (m_obj != -1) destroy(); glGenRenderbuffersEXT(1, &m_obj); Q_ASSERT(!glIsRenderbufferEXT(m_obj)); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_obj); Q_ASSERT(glIsRenderbufferEXT(m_obj)); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamp, internal_format, size.width(), size.height()); mglCheckErrors("renderBuf"); }
PIGLIT_GL_TEST_CONFIG_END void piglit_init(int argc, char **argv) { glGetIntegerv(GL_MAX_SAMPLES_EXT, &numSamples); glGenFramebuffersEXT(1, &framebuffer); glGenRenderbuffersEXT(1, &renderbuffer); glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer); glBindRenderbufferEXT(GL_RENDERBUFFER, renderbuffer); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, numSamples, GL_RGBA, WIDTH, HEIGHT); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); glEnable (GL_MULTISAMPLE); }
void vsx_texture::init_buffer(int width, int height, bool float_texture, bool alpha, bool enable_multisample) { GLenum gl_error; glGetError(); locked = false; prev_buf = 0; #ifndef VSXU_OPENGL_ES glewInit(); #endif int i_width = width; int i_height = height; if ( !has_buffer_support() ) { printf("vsx_texture error: No FBO available!\n"); return; } GLint prev_buf_l; GLuint tex_id; glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, (GLint *)&prev_buf_l); HANDLE_GL_ERROR // color buffer glGenRenderbuffersEXT(1, &colorBuffer); HANDLE_GL_ERROR glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, colorBuffer); HANDLE_GL_ERROR if(enable_multisample && GLEW_EXT_framebuffer_multisample) { if (float_texture) { glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, 4, alpha?GL_RGBA16F_ARB:GL_RGB16F_ARB, width, height); HANDLE_GL_ERROR } else { glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, 4, alpha?GL_RGBA8:GL_RGB8, width, height); HANDLE_GL_ERROR } }
void piglit_init(int argc, char **argv) { GLint max_samples; GLuint rb, fb, tex; GLenum status; bool pass = true; piglit_require_extension("GL_EXT_framebuffer_multisample"); glGetIntegerv(GL_MAX_SAMPLES, &max_samples); glGenFramebuffersEXT(1, &fb); glBindFramebufferEXT(GL_FRAMEBUFFER, fb); glGenRenderbuffersEXT(1, &rb); glBindRenderbufferEXT(GL_RENDERBUFFER, rb); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, max_samples, GL_RGBA, 1, 1); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb); glDrawBuffer(GL_COLOR_ATTACHMENT0); glReadBuffer(GL_COLOR_ATTACHMENT0); status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { fprintf(stderr, "FBO incomplete\n"); piglit_report_result(PIGLIT_FAIL); } glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); /* Finally, the actual test! */ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0); if (!piglit_check_gl_error(GL_INVALID_FRAMEBUFFER_OPERATION)) piglit_report_result(PIGLIT_FAIL); glDeleteTextures(1, &tex); glDeleteRenderbuffersEXT(1, &rb); glDeleteFramebuffersEXT(1, &fb); piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }
GLDepthStencilView::GLDepthStencilView(uint32 width, uint32 height, ElementFormat ef, uint32 sampleCount, uint32 sampleQuality): mLevel(-1), mRBO(0), mSampleCount(sampleCount), mSampleQuaility(sampleQuality) { mWidth = width; mHeight = height; mElementFormat = ef; CHECK_GL_CALL(glGenRenderbuffers(1, &mRBO)); if(mRBO) { glBindRenderbuffer(GL_RENDERBUFFER, mRBO); if(mSampleCount <= 1 || !glRenderbufferStorageMultisampleEXT) glRenderbufferStorage(GL_RENDERBUFFER, element_format_to_gl_format(ef), width, height); else glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, mSampleCount, element_format_to_gl_format(ef), width, height); } }
void piglit_init(int argc, char **argv) { GLint max_samples, samples, prev_rb_samples = 0; GLuint rb; bool pass = true; piglit_require_extension("GL_EXT_framebuffer_multisample"); glGetIntegerv(GL_MAX_SAMPLES, &max_samples); glGenRenderbuffersEXT(1, &rb); glBindRenderbufferEXT(GL_RENDERBUFFER, rb); printf("%10s %10s\n", "requested", "result"); for (samples = 0; samples <= max_samples; samples++) { GLint rb_samples; glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, GL_RGBA, 1, 1); glGetRenderbufferParameterivEXT(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &rb_samples); if ((rb_samples < prev_rb_samples) || (samples == 0 && rb_samples != 0) || (samples > 0 && rb_samples < samples)) { fprintf(stderr, "%10d %10d (ERROR)\n", samples, rb_samples); pass = false; } else { printf("%10d %10d\n", samples, rb_samples); } prev_rb_samples = rb_samples; } glDeleteRenderbuffersEXT(1, &rb); piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }
void LLMultisampleBuffer::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; glGenRenderbuffersEXT(1, &tex); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tex); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, color_fmt, mResX, mResY); stop_glerror(); if (mFBO) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset, GL_RENDERBUFFER_EXT, tex); stop_glerror(); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); switch (status) { case GL_FRAMEBUFFER_COMPLETE_EXT: break; default: llerrs << "WTF? " << std::hex << status << llendl; break; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } mTex.push_back(tex); }
GLDepthStencilView::GLDepthStencilView(const TexturePtr& texture, int32 level): mTexture(texture), mLevel(level), mRBO(0), mSampleCount(1), mSampleQuaility(1) { GLTexture2D* glTexture = (GLTexture2D*)mTexture.get(); mTex = (GLuint)glTexture->getTextureId(); mWidth = glTexture->width(0); mHeight = glTexture->height(0); mElementFormat = glTexture->format(); CHECK_GL_CALL(glGenRenderbuffers(1, &mRBO)); if(mRBO) { CHECK_GL_CALL(glBindRenderbuffer(GL_RENDERBUFFER, mRBO)); if(mSampleCount <= 1 || !glRenderbufferStorageMultisampleEXT) { CHECK_GL_CALL(glRenderbufferStorage(GL_RENDERBUFFER, element_format_to_gl_format(mElementFormat), mWidth, mHeight)); } else { CHECK_GL_CALL(glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, mSampleCount, element_format_to_gl_format(mElementFormat), mWidth, mHeight)); } } }
void GLTexture::init() { if (m_fbType == ENone) Log(ETrace, "Uploading a texture : %s", toString().c_str()); else Log(ETrace, "Creating a framebuffer : %s", toString().c_str()); if (m_samples > 1) { int maxSamples = 1; if (GLEW_ARB_texture_multisample) glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples); if (m_samples > maxSamples) { Log(EWarn, "Attempted to create a multisample framebuffer " "with an unsupported number of samples (requested=%i, supported=%i)", m_samples, maxSamples); m_samples = maxSamples; } } lookupGLConstants(); /* Generate an identifier */ glGenTextures(1, &m_id); /* Bind to the texture */ glBindTexture(m_glType, m_id); /* Set the texture filtering / wrapping modes (don't do this for multisample textures)*/ if (!((m_fbType & EColorBuffer) && m_samples > 1)) configureTexture(); /* Multisample textures don't have these parameters */ if (m_fbType == ENone) { Assert(m_samples == 1); refresh(); } else { /* Create the FBO and bind it */ glGenFramebuffersEXT(1, &m_fboId); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId); AssertEx(glIsFramebufferEXT(m_fboId), "Creating an FBO failed"); bool depthAsTexture = m_fbType & EDepthBuffer; switch (m_fbType) { case EColorAndDepthBuffer: case EColorBuffer: { if (m_type == ETexture2D) { if (!depthAsTexture) { glGenRenderbuffersEXT(1, &m_depthId); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthId); if (m_samples == 1) glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT32, m_size.x, m_size.y); else glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_samples, GL_DEPTH_COMPONENT32, m_size.x, m_size.y); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthId); } else { glGenTextures(1, &m_depthId); glBindTexture(m_glType, m_depthId); configureTexture(); glTexParameteri(m_glType, GL_TEXTURE_COMPARE_MODE, GL_NONE); glTexParameteri(m_glType, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); if (m_samples == 1) glTexImage2D(m_glType, 0, GL_DEPTH_COMPONENT32, m_size.x, m_size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); else glTexImage2DMultisample(m_glType, m_samples, GL_DEPTH_COMPONENT32, m_size.x, m_size.y, GL_FALSE); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, m_glType, m_depthId, 0); glBindTexture(m_glType, m_id); } if (m_samples == 1) glTexImage2D(m_glType, 0, m_internalFormat, m_size.x, m_size.y, 0, m_format, m_dataFormat, NULL); else glTexImage2DMultisample(m_glType, m_samples, m_internalFormat, m_size.x, m_size.y, GL_FALSE); if (isMipMapped()) glGenerateMipmapEXT(m_glType); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, m_glType, m_id, 0); } else if (m_type == ETextureCubeMap) { Assert(m_size.x == m_size.y && math::isPowerOfTwo(m_size.x)); Assert(m_fbType == EColorBuffer); Assert(m_samples == 1); for (int i=0; i<6; i++) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, m_internalFormat, m_size.x, m_size.y, 0, m_format, m_dataFormat, NULL); if (isMipMapped()) glGenerateMipmapEXT(m_glType); if (depthAsTexture) { /* Generate an identifier */ glGenTextures(1, &m_depthId); glBindTexture(m_glType, m_depthId); glTexParameteri(m_glType, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(m_glType, GL_TEXTURE_MIN_FILTER, GL_LINEAR); for (int i=0; i<6; i++) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT32, m_size.x, m_size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); if (GLEW_EXT_geometry_shader4) activateSide(-1); else activateSide(0); } else { glGenRenderbuffersEXT(1, &m_depthId); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthId); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT32, m_size.x, m_size.y); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthId); activateSide(0); } } else { Log(EError, "Unsupported texture type!"); } } break; case EDepthBuffer: Assert(m_samples == 1); if (m_depthMode == ECompare) { glTexParameteri(m_glType, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); glTexParameteri(m_glType, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); } if (m_type == ETexture2D) { /* Allocate the texture memory */ glTexImage2D(m_glType, 0, m_internalFormat, m_size.x, m_size.y, 0, GL_DEPTH_COMPONENT, m_dataFormat, NULL); /* Attach the texture as a depth target */ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, m_glType, m_id, 0); } else if (m_type == ETextureCubeMap) { Assert(m_size.x == m_size.y && math::isPowerOfTwo(m_size.x)); for (int i=0; i<6; i++) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, m_internalFormat, m_size.x, m_size.y, 0, m_format, m_dataFormat, NULL); if (GLEW_EXT_geometry_shader4) activateSide(-1); else activateSide(0); } else { Log(EError, "Unsupported texture type!"); } glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); break; default: Log(EError, "Invalid render buffer type!"); } GLenum errorStatusID = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); std::string errorStatus; switch (errorStatusID) { case GL_FRAMEBUFFER_COMPLETE_EXT: break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: errorStatus = "Incomplete attachment"; break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: errorStatus = "Unsupported framebuffer format"; break; case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: errorStatus = "Incomplete framebuffer - duplicate attachment"; break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: errorStatus = "Incomplete framebuffer - missing attachment"; break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: errorStatus = "Incomplete framebuffer - invalid dimensions"; break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: errorStatus = "Incomplete framebuffer - no draw buffer"; break; case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: errorStatus = "Incomplete framebuffer - invalid formats"; break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: errorStatus = "Incomplete framebuffer - no readbuffer"; break; case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: errorStatus = "Incomplete multisample framebuffer"; break; case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: errorStatus = "Incomplete layer targets"; break; default: errorStatus = "Unknown error status"; break; } if (!errorStatus.empty()) Log(EError, "FBO Error 0x%x: %s!\nFramebuffer configuration: %s", errorStatusID, errorStatus.c_str(), toString().c_str()); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, GL_NONE); } glBindTexture(m_glType, GL_NONE); }
void ofxFBOTexture::allocate(int w, int h, int internalGlDataType, int numSamples) { _isActive = false; //OpenGL supported technologies checking. if(!bSupportsFBO){ ofLog(OF_LOG_ERROR, "ofxFBOTexture: GL_EXT_framebuffer_object not supported by current OpenGL renderer. " " For Apple machines, more info at http://developer.apple.com/graphicsimaging/opengl/capabilities"); return; } if(!bSupportsMulti && numSamples){ ofLog(OF_LOG_WARNING, "ofxFBOTexture: GL_EXT_framebuffer_multisample not supported by current OpenGL renderer." " Falling back to non-multisampled mode. To disable this message, specify 0 samples." " Apple machines, more info at http://developer.apple.com/graphicsimaging/opengl/capabilities"); numSamples = 0; } if(!bSupportsBlit && numSamples){ //if there's no blit, then it's not worth using multi ofLog(OF_LOG_WARNING, "ofxFBOTexture: GL_EXT_framebuffer_blit not supported by current OpenGL renderer." " Falling back to non-multisampled mode. To disable this message, specify 0 samples." " Apple machines, more info at http://developer.apple.com/graphicsimaging/opengl/capabilities"); numSamples = 0; } if(maxSamples < numSamples){ ofLog(OF_LOG_WARNING, "ofxFBOTexture: requested samples too high. Using GL_SAMPLES instead."); numSamples = maxSamples; } //validate requested dimensions to see that they are within limits. if(maxTextureSize < w || maxRenderBufferSize < w){ ofLog(OF_LOG_WARNING, "ofxFBOTexture: requested width was too large. Using largest allowed value instead."); if(maxTextureSize < w) w = maxTextureSize; if(maxRenderBufferSize < w) w = maxRenderBufferSize; } if( maxTextureSize < h || maxRenderBufferSize < h){ ofLog(OF_LOG_WARNING, "ofxFBOTexture: requested height was too large. Using largest allowed value instead."); if(maxTextureSize < h) h = maxTextureSize; if(maxRenderBufferSize < h) h = maxRenderBufferSize; } /** validates arg3 for legacy function calling style i dont check for 1 because 1 is a valid internal color format so we're not sure if the person is passing a boolean or a color format so we can't accuse them of doing the legacy boolean thing. Even if that stops the FBO, the other color format error will help them out. */ if(internalGlDataType==0){ ofLog(OF_LOG_WARNING, "ofxFBOTexture::allocate( _ , _ , HERE , _ ) " "The calling statement passed a boolean value like an older version of FBO object. " "This argument has changed to be a color format " "like GL_RGB, GL_RGBA, GL_RGBA16F_ARB, and GL_RGBA32F_ARB. " "Defaulting to GL_RGBA."); internalGlDataType = GL_RGBA; } // attempt to free the previous bound texture, if we can: clean(); texData.width = w; texData.height = h; this->numSamples = numSamples; /* *GLEE_ARB_texture_rectangle thows errors in the latest from github (post 0062?) so i commented this out */ //#ifndef TARGET_OPENGLES // if (GLEE_ARB_texture_rectangle){ // texData.tex_w = w; // texData.tex_h = h; // texData.textureTarget = GL_TEXTURE_RECTANGLE_ARB; // } else //#endif // { texData.tex_w = ofNextPow2(w); texData.tex_h = ofNextPow2(h); // } //#ifndef TARGET_OPENGLES // if (GLEE_ARB_texture_rectangle){ // texData.tex_t = w; // texData.tex_u = h; // } else //#endif // { texData.tex_t = w/texData.tex_w; texData.tex_u = h/texData.tex_h; //} texData.width = w; texData.height = h; texData.bFlipTexture = true; texData.glTypeInternal = internalGlDataType; #ifndef TARGET_OPENGLES switch(texData.glTypeInternal) { case GL_RGBA32F_ARB: case GL_RGBA16F_ARB: texData.glType = GL_RGBA; texData.pixelType = GL_FLOAT; pixels = new float[w * h * 4]; break; default: texData.glType = texData.glTypeInternal; texData.pixelType = GL_UNSIGNED_BYTE; pixels = new float[w * h * 4]; break; } #else texData.glType = GL_RGBA; texData.pixelType = GL_UNSIGNED_BYTE; pixels = new unsigned char[w * h * 4]; #endif // create & setup texture glGenTextures(1, (GLuint *)&texData.textureID); // could be more then one, but for now, just one glBindTexture(texData.textureTarget, (GLuint)texData.textureID); glTexParameterf(texData.textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(texData.textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameterf(texData.textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(texData.textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(texData.textureTarget, 0, texData.glTypeInternal, texData.tex_w, texData.tex_h, 0, texData.glType, texData.pixelType, 0); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifndef TARGET_OPENGLES glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, (GLint *) &oldFramebuffer); if(numSamples ){ // MULTISAMPLE // //THEO Create the render buffer for depth glGenRenderbuffersEXT(1, &depthBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_DEPTH_COMPONENT, texData.tex_w, texData.tex_h); //THEO multi sampled color buffer glGenRenderbuffersEXT(1, &colorBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, colorBuffer); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, texData.glTypeInternal, texData.tex_w, texData.tex_h); //THEO create fbo for multi sampled content and attach depth and color buffers to it glGenFramebuffersEXT(1, &mfbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mfbo); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, colorBuffer); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer); }else{ //THEO Create the render buffer for depth glGenRenderbuffersEXT(1, &depthBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, texData.tex_w, texData.tex_h); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer); } // create & setup FBO glGenFramebuffersEXT(1, &fbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); // attach it to the FBO so we can render to it glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texData.textureTarget, (GLuint)texData.textureID, 0); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if(status != GL_FRAMEBUFFER_COMPLETE_EXT) { //validate arg3 after the fact because it's worth letting them try that format. if(internalGlDataType != GL_RGBA && internalGlDataType != GL_RGB && internalGlDataType != GL_RGBA16F_ARB && internalGlDataType != GL_RGBA32F_ARB){ ofLog(OF_LOG_ERROR, "ofxFBOTexture: Failed to initialize. " "I noticed that the calling statement did not passed an expected color format " "like GL_RGB, GL_RGBA, GL_RGBA16F_ARB, and GL_RGBA32F_ARB. You might try one of those. " "ofxFBOTexture::allocate( _ , _ , HERE , _ ) "); }else{ ofLog(OF_LOG_ERROR, "ofxFBOTexture: Failed to initialize."); } std::exit(1); } clear(0, 0, 0, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFramebuffer); #else if(numSamples ){ ofLog(OF_LOG_WARNING, "Multi-sampling not supported on OpenGL ES"); }else{ } glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, (GLint *) &oldFramebuffer); // create & setup FBO glGenFramebuffersOES(1, &fbo); glBindFramebufferOES(GL_FRAMEBUFFER_OES, fbo); // attach it to the FBO so we can render to it glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, texData.textureTarget, (GLuint)texData.textureID, 0); glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldFramebuffer); #endif texData.bAllocated = true; }
void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, QGLFramebufferObject::Attachment attachment, GLenum texture_target, GLenum internal_format, GLint samples) { QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); fbo_guard.setContext(ctx); bool ext_detected = (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject); if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(ctx))) return; size = sz; target = texture_target; // texture dimensions QT_RESET_GLERROR(); // reset error state GLuint fbo = 0; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo); fbo_guard.setId(fbo); glDevice.setFBO(q, attachment); QT_CHECK_GLERROR(); // init texture if (samples == 0) { glGenTextures(1, &texture); glBindTexture(target, texture); glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); #ifndef QT_OPENGL_ES glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #else glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #endif glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, texture, 0); QT_CHECK_GLERROR(); valid = checkFramebufferStatus(); glBindTexture(target, 0); color_buffer = 0; } else { GLint maxSamples; glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples); samples = qBound(0, int(samples), int(maxSamples)); glGenRenderbuffers(1, &color_buffer); glBindRenderbuffer(GL_RENDERBUFFER_EXT, color_buffer); if (glRenderbufferStorageMultisampleEXT && samples > 0) { glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, internal_format, size.width(), size.height()); } else { samples = 0; glRenderbufferStorage(GL_RENDERBUFFER_EXT, internal_format, size.width(), size.height()); } glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, color_buffer); QT_CHECK_GLERROR(); valid = checkFramebufferStatus(); if (valid) glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &samples); } // In practice, a combined depth-stencil buffer is supported by all desktop platforms, while a // separate stencil buffer is not. On embedded devices however, a combined depth-stencil buffer // might not be supported while separate buffers are, according to QTBUG-12861. if (attachment == QGLFramebufferObject::CombinedDepthStencil && (QGLExtensions::glExtensions() & QGLExtensions::PackedDepthStencil)) { // depth and stencil buffer needs another extension glGenRenderbuffers(1, &depth_buffer); Q_ASSERT(!glIsRenderbuffer(depth_buffer)); glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_buffer); Q_ASSERT(glIsRenderbuffer(depth_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); else glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); stencil_buffer = depth_buffer; glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, stencil_buffer); valid = checkFramebufferStatus(); if (!valid) { glDeleteRenderbuffers(1, &depth_buffer); stencil_buffer = depth_buffer = 0; } } if (depth_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil || (attachment == QGLFramebufferObject::Depth))) { glGenRenderbuffers(1, &depth_buffer); Q_ASSERT(!glIsRenderbuffer(depth_buffer)); glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_buffer); Q_ASSERT(glIsRenderbuffer(depth_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) { #ifdef QT_OPENGL_ES if (QGLExtensions::glExtensions() & QGLExtensions::Depth24) { glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH_COMPONENT24_OES, size.width(), size.height()); } else { glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH_COMPONENT16, size.width(), size.height()); } #else glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH_COMPONENT, size.width(), size.height()); #endif } else { #ifdef QT_OPENGL_ES if (QGLExtensions::glExtensions() & QGLExtensions::Depth24) { glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_OES, size.width(), size.height()); } else { glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, size.width(), size.height()); } #else glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height()); #endif } glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_buffer); valid = checkFramebufferStatus(); if (!valid) { glDeleteRenderbuffers(1, &depth_buffer); depth_buffer = 0; } } if (stencil_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil)) { glGenRenderbuffers(1, &stencil_buffer); Q_ASSERT(!glIsRenderbuffer(stencil_buffer)); glBindRenderbuffer(GL_RENDERBUFFER_EXT, stencil_buffer); Q_ASSERT(glIsRenderbuffer(stencil_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) { #ifdef QT_OPENGL_ES glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_STENCIL_INDEX8_EXT, size.width(), size.height()); #else glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_STENCIL_INDEX, size.width(), size.height()); #endif } else { #ifdef QT_OPENGL_ES glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, size.width(), size.height()); #else glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, size.width(), size.height()); #endif } glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, stencil_buffer); valid = checkFramebufferStatus(); if (!valid) { glDeleteRenderbuffers(1, &stencil_buffer); stencil_buffer = 0; } } // The FBO might have become valid after removing the depth or stencil buffer. valid = checkFramebufferStatus(); if (depth_buffer && stencil_buffer) { fbo_attachment = QGLFramebufferObject::CombinedDepthStencil; } else if (depth_buffer) { fbo_attachment = QGLFramebufferObject::Depth; } else { fbo_attachment = QGLFramebufferObject::NoAttachment; } glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); if (!valid) { if (color_buffer) glDeleteRenderbuffers(1, &color_buffer); else glDeleteTextures(1, &texture); if (depth_buffer) glDeleteRenderbuffers(1, &depth_buffer); if (stencil_buffer && depth_buffer != stencil_buffer) glDeleteRenderbuffers(1, &stencil_buffer); glDeleteFramebuffers(1, &fbo); fbo_guard.setId(0); } QT_CHECK_GLERROR(); format.setTextureTarget(target); format.setSamples(int(samples)); format.setAttachment(fbo_attachment); format.setInternalTextureFormat(internal_format); }
void piglit_init(int argc, char **argv) { GLint max_samples, sample_buffers, samples, rb_samples; GLuint rb, fb; GLenum status; bool pass = true; int i; piglit_require_extension("GL_EXT_framebuffer_multisample"); glGetIntegerv(GL_MAX_SAMPLES, &max_samples); glGenFramebuffersEXT(1, &fb); glBindFramebufferEXT(GL_FRAMEBUFFER, fb); glDrawBuffer(GL_COLOR_ATTACHMENT0); glReadBuffer(GL_COLOR_ATTACHMENT0); for (i = 0; i < max_samples; i++) { glGenRenderbuffersEXT(1, &rb); glBindRenderbufferEXT(GL_RENDERBUFFER, rb); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, max_samples, GL_RGBA, 1, 1); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb); status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { fprintf(stderr, "FBO incomplete\n"); piglit_report_result(PIGLIT_FAIL); } glGetRenderbufferParameterivEXT(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &rb_samples); glGetIntegerv(GL_SAMPLES, &samples); if (rb_samples != samples) { fprintf(stderr, "FBO reported GL_SAMPLES %d for " "rb samples %d\n", samples, rb_samples); pass = false; } glGetIntegerv(GL_SAMPLE_BUFFERS, &sample_buffers); if ((rb_samples != 0) != (sample_buffers == 1)) { fprintf(stderr, "FBO reported GL_SAMPLE_BUFFERS %d for " "rb samples %d\n", sample_buffers, samples); pass = false; } glDeleteRenderbuffersEXT(1, &rb); } glDeleteFramebuffersEXT(1, &fb); piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }
void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, QGLFramebufferObject::Attachment attachment, GLenum texture_target, GLenum internal_format, GLint samples) { QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); fbo_guard.setContext(ctx); bool ext_detected = (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject); if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(ctx))) return; size = sz; target = texture_target; // texture dimensions QT_RESET_GLERROR(); // reset error state GLuint fbo = 0; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo); fbo_guard.setId(fbo); glDevice.setFBO(q, attachment); QT_CHECK_GLERROR(); // init texture if (samples == 0) { glGenTextures(1, &texture); glBindTexture(target, texture); glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); #ifndef QT_OPENGL_ES glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #else glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #endif glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, texture, 0); QT_CHECK_GLERROR(); valid = checkFramebufferStatus(); glBindTexture(target, 0); color_buffer = 0; } else { GLint maxSamples; glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples); samples = qBound(1, int(samples), int(maxSamples)); glGenRenderbuffers(1, &color_buffer); glBindRenderbuffer(GL_RENDERBUFFER_EXT, color_buffer); if (glRenderbufferStorageMultisampleEXT) { glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, internal_format, size.width(), size.height()); } else { samples = 0; glRenderbufferStorage(GL_RENDERBUFFER_EXT, internal_format, size.width(), size.height()); } glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, color_buffer); QT_CHECK_GLERROR(); valid = checkFramebufferStatus(); if (valid) glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &samples); } if (attachment == QGLFramebufferObject::CombinedDepthStencil && (QGLExtensions::glExtensions() & QGLExtensions::PackedDepthStencil)) { // depth and stencil buffer needs another extension glGenRenderbuffers(1, &depth_stencil_buffer); Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer)); glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer); Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); else glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); GLint i = 0; glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_buffer); fbo_attachment = QGLFramebufferObject::CombinedDepthStencil; valid = checkFramebufferStatus(); if (!valid) glDeleteRenderbuffers(1, &depth_stencil_buffer); } else if (attachment == QGLFramebufferObject::Depth || attachment == QGLFramebufferObject::CombinedDepthStencil) { glGenRenderbuffers(1, &depth_stencil_buffer); Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer)); glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer); Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer)); if (samples != 0 && glRenderbufferStorageMultisampleEXT) { #ifdef QT_OPENGL_ES #define GL_DEPTH_COMPONENT16 0x81A5 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH_COMPONENT16, size.width(), size.height()); #else glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, GL_DEPTH_COMPONENT, size.width(), size.height()); #endif } else { #ifdef QT_OPENGL_ES #define GL_DEPTH_COMPONENT16 0x81A5 glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, size.width(), size.height()); #else glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height()); #endif } GLint i = 0; glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_buffer); fbo_attachment = QGLFramebufferObject::Depth; valid = checkFramebufferStatus(); if (!valid) glDeleteRenderbuffers(1, &depth_stencil_buffer); } else { fbo_attachment = QGLFramebufferObject::NoAttachment; } glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); if (!valid) { if (color_buffer) glDeleteRenderbuffers(1, &color_buffer); else glDeleteTextures(1, &texture); glDeleteFramebuffers(1, &fbo); fbo_guard.setId(0); } QT_CHECK_GLERROR(); format.setTextureTarget(target); format.setSamples(int(samples)); format.setAttachment(fbo_attachment); format.setInternalTextureFormat(internal_format); }
void ofxFBOTexture::allocate(int w, int h, bool autoClear, int numSamples) { _isActive = false; texData.width = w; texData.height = h; if( numSamples == 0 ){ bUseMultiSample = false; }else{ bUseMultiSample = true; } if (GLEE_ARB_texture_rectangle){ texData.tex_w = w; texData.tex_h = h; texData.textureTarget = GL_TEXTURE_RECTANGLE_ARB; } else { texData.tex_w = ofNextPow2(w); texData.tex_h = ofNextPow2(h); } if (GLEE_ARB_texture_rectangle){ texData.tex_t = w; texData.tex_u = h; } else { texData.tex_t = 1.0f; texData.tex_u = 1.0f; } // attempt to free the previous bound texture, if we can: clean(); texData.width = w; texData.height = h; texData.bFlipTexture = true; texData.glType = GL_RGBA; this->autoClear = autoClear; if( bUseMultiSample ){ // MULTISAMPLE // //THEO Create the render buffer for depth glGenRenderbuffersEXT(1, &depthBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_DEPTH_COMPONENT, texData.tex_w, texData.tex_h); //THEO multi sampled color buffer glGenRenderbuffersEXT(1, &colorBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, colorBuffer); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_RGBA8, texData.tex_w, texData.tex_h); //THEO create fbo for multi sampled content and attach depth and color buffers to it glGenFramebuffersEXT(1, &mfbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mfbo); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, colorBuffer); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer); }else{ //THEO Create the render buffer for depth glGenRenderbuffersEXT(1, &depthBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, texData.tex_w, texData.tex_h); } // NORMAL // // create & setup texture glGenTextures(1, (GLuint *)(&texData.textureID)); // could be more then one, but for now, just one glBindTexture(texData.textureTarget, (GLuint)(texData.textureID)); glTexParameterf(texData.textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(texData.textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameterf(texData.textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(texData.textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(texData.textureTarget, 0, texData.glType, texData.tex_w, texData.tex_h, 0, texData.glType, GL_UNSIGNED_BYTE, 0); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // create & setup FBO glGenFramebuffersEXT(1, &fbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); // attach it to the FBO so we can render to it glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texData.textureTarget, (GLuint)texData.textureID, 0); if( !bUseMultiSample ){ // Attach the depth render buffer to the FBO as it's depth attachment glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer); } GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if(status != GL_FRAMEBUFFER_COMPLETE_EXT) { cout<<"glBufferTexture failed to initialize. Perhaps your graphics card doesnt support the framebuffer extension? If you are running osx prior to system 10.5, that could be the cause"<<endl; std::exit(1); } clear(0, 0, 0, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); texData.bAllocated = true; }
void WebGraphicsContext3DDefaultImpl::reshape(int width, int height) { #ifdef RENDER_TO_DEBUGGING_WINDOW SetWindowPos(m_canvasWindow, HWND_TOP, 0, 0, width, height, SWP_NOMOVE); ShowWindow(m_canvasWindow, SW_SHOW); #endif m_cachedWidth = width; m_cachedHeight = height; makeContextCurrent(); #ifndef RENDER_TO_DEBUGGING_WINDOW #ifdef USE_TEXTURE_RECTANGLE_FOR_FRAMEBUFFER // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on Mac OS X GLenum target = GL_TEXTURE_RECTANGLE_ARB; #else GLenum target = GL_TEXTURE_2D; #endif if (!m_texture) { // Generate the texture object m_texture = createTextureObject(target); // Generate the framebuffer object glGenFramebuffersEXT(1, &m_fbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); m_boundFBO = m_fbo; if (m_attributes.depth || m_attributes.stencil) glGenRenderbuffersEXT(1, &m_depthStencilBuffer); // Generate the multisample framebuffer object if (m_attributes.antialias) { glGenFramebuffersEXT(1, &m_multisampleFBO); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); m_boundFBO = m_multisampleFBO; glGenRenderbuffersEXT(1, &m_multisampleColorBuffer); if (m_attributes.depth || m_attributes.stencil) glGenRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer); } } GLint internalColorFormat, colorFormat, internalDepthStencilFormat = 0; if (m_attributes.alpha) { internalColorFormat = GL_RGBA8; colorFormat = GL_RGBA; } else { internalColorFormat = GL_RGB8; colorFormat = GL_RGB; } if (m_attributes.stencil || m_attributes.depth) { // We don't allow the logic where stencil is required and depth is not. // See GraphicsContext3DInternal constructor. if (m_attributes.stencil && m_attributes.depth) internalDepthStencilFormat = GL_DEPTH24_STENCIL8_EXT; else internalDepthStencilFormat = GL_DEPTH_COMPONENT; } bool mustRestoreFBO = false; // Resize multisampling FBO if (m_attributes.antialias) { GLint maxSampleCount; glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSampleCount); GLint sampleCount = std::min(8, maxSampleCount); if (m_boundFBO != m_multisampleFBO) { mustRestoreFBO = true; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); } glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalColorFormat, width, height); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); if (m_attributes.stencil || m_attributes.depth) { glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalDepthStencilFormat, width, height); if (m_attributes.stencil) glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); if (m_attributes.depth) glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); } glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { printf("GraphicsContext3D: multisampling framebuffer was incomplete\n"); // FIXME: cleanup. notImplemented(); } } // Resize regular FBO if (m_boundFBO != m_fbo) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); mustRestoreFBO = true; } glBindTexture(target, m_texture); glTexImage2D(target, 0, internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, m_texture, 0); glBindTexture(target, 0); if (!m_attributes.antialias && (m_attributes.stencil || m_attributes.depth)) { glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthStencilBuffer); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalDepthStencilFormat, width, height); if (m_attributes.stencil) glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); if (m_attributes.depth) glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); } GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { printf("WebGraphicsContext3DDefaultImpl: framebuffer was incomplete\n"); // FIXME: cleanup. notImplemented(); } if (mustRestoreFBO) glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); #endif // RENDER_TO_DEBUGGING_WINDOW #ifdef FLIP_FRAMEBUFFER_VERTICALLY if (m_scanline) { delete[] m_scanline; m_scanline = 0; } m_scanline = new unsigned char[width * 4]; #endif // FLIP_FRAMEBUFFER_VERTICALLY GLbitfield clearMask = GL_COLOR_BUFFER_BIT; if (m_attributes.stencil) clearMask |= GL_STENCIL_BUFFER_BIT; if (m_attributes.depth) clearMask |= GL_DEPTH_BUFFER_BIT; glClear(clearMask); }
bool RenderToFrameBuffer::Init(const structRenderTargetInfo & rttInfo) { // Setup our FBO glGenFramebuffersEXT(1, &m_fbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); if ((rttInfo.fSuperSample > 0 || rttInfo.bPhysicalScreen) && rttInfo.iWidthSS > 0 && rttInfo.iHeightSS > 0) { m_iWidth = (int)((float)rttInfo.iWidthSS * rttInfo.fSuperSample + 0.5f); m_iHeight = (int)((float)rttInfo.iHeightSS * rttInfo.fSuperSample + 0.5f); } else { m_iWidth = rttInfo.iWidth; m_iHeight = rttInfo.iHeight; } bool bCoverage = false; if ((rttInfo.iMultiSample > 0) && RenderToFrameBuffer::IsAvailable()/*[2]*/) { m_iMultiSample = rttInfo.iMultiSample; if (m_iMultiSample > MAX_AAModes) m_iMultiSample = MAX_AAModes; // coverage supported ? // if (glRenderbufferStorageMultisampleCoverageNV) // bCoverage = true; // else bCoverage = false; } else m_iMultiSample = 0; int ds = 0; int cs = 0; if (m_iMultiSample > 0) { ds = g_AAModes[m_iMultiSample-1].ds; cs = bCoverage ? g_AAModes[m_iMultiSample-1].cs : 0; } if (rttInfo.eFormat != GL_DEPTH_COMPONENT) { // Create the render buffer for depth glGenRenderbuffersEXT(1, &m_depthBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer); GLenum internalFormat = rttInfo.bStencil ? GL_DEPTH24_STENCIL8_EXT : GL_DEPTH_COMPONENT; if (m_iMultiSample > 0) { glGenFramebuffersEXT(1, &m_fboMS); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboMS); if (cs==0) { glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, ds, internalFormat, m_iWidth, m_iHeight); // check the number of samples GLint qds = 0; glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &qds); if (qds < ds) { Clean(); return false; } } else { // glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, cs, ds, internalFormat, m_iWidth, m_iHeight); // check the number of samples GLint qds = 0; GLint qcs = 0; glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_COVERAGE_SAMPLES_NV, &qcs); glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_COLOR_SAMPLES_NV, &qds); if ((qcs < cs) || (qds < ds)) { Clean(); return false; } } } else glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalFormat, m_iWidth, m_iHeight); // Attach the depth render buffer to the FBO as it's depth attachment glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer); if (rttInfo.bStencil) glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer); if (m_iMultiSample > 0) { glGenRenderbuffersEXT(1, &m_colorMS); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_colorMS); if (cs==0) { glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, ds, GL_RGBA8, m_iWidth, m_iHeight); // check the number of samples GLint qds = 0; glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &qds); if (qds < ds) { Clean(); return false; } } else { // glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, cs, ds, GL_RGBA8, m_iWidth, m_iHeight); // check the number of samples GLint qds = 0; GLint qcs = 0; glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_COVERAGE_SAMPLES_NV, &qcs); glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_COLOR_SAMPLES_NV, &qds); if ((qcs < cs) || (qds < ds)) { Clean(); return false; } } // attach the multisampled color buffer glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_colorMS); } } else { // The following is REQUIRED or the FBO will not be resolved (since we have no color buffer here) // Also note that these states are only valid for the FBO state, so can be done once during init glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); } m_eFormat = rttInfo.eFormat; m_eType = rttInfo.eType; m_iFiltering = rttInfo.iFiltering; m_bMipMap = RenderToFrameBuffer::IsAvailable()/*[1]*/ && rttInfo.bMipMap; m_bBindDepth = rttInfo.m_bBindDepth; m_bInitialized = true; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind the FBO for now return true; }
void ofxFBOTexture::allocate(int w, int h, int internalGlDataType, int numSamples) { _isActive = false; // attempt to free the previous bound texture, if we can: clean(); texData.width = w; texData.height = h; this->numSamples = numSamples; #ifndef TARGET_OPENGLES if (GLEE_ARB_texture_rectangle){ texData.tex_w = w; texData.tex_h = h; texData.textureTarget = GL_TEXTURE_RECTANGLE_ARB; } else #endif { texData.tex_w = ofNextPow2(w); texData.tex_h = ofNextPow2(h); } #ifndef TARGET_OPENGLES if (GLEE_ARB_texture_rectangle){ texData.tex_t = w; texData.tex_u = h; } else #endif { texData.tex_t = w/texData.tex_w; texData.tex_u = h/texData.tex_h; } texData.width = w; texData.height = h; texData.bFlipTexture = true; texData.glTypeInternal = internalGlDataType; #ifndef TARGET_OPENGLES switch(texData.glTypeInternal) { case GL_RGBA32F_ARB: case GL_RGBA16F_ARB: texData.glType = GL_RGBA; texData.pixelType = GL_FLOAT; pixels = new float[w * h * 4]; break; default: texData.glType = GL_LUMINANCE; texData.pixelType = GL_UNSIGNED_BYTE; pixels = new unsigned char[w * h * 4]; } #else texData.glType = GL_RGBA; texData.pixelType = GL_UNSIGNED_BYTE; pixels = new unsigned char[w * h * 4]; #endif // create & setup texture glGenTextures(1, (GLuint *)&texData.textureID); // could be more then one, but for now, just one glBindTexture(texData.textureTarget, (GLuint)texData.textureID); glTexParameterf(texData.textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(texData.textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameterf(texData.textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(texData.textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(texData.textureTarget, 0, texData.glTypeInternal, texData.tex_w, texData.tex_h, 0, texData.glType, texData.pixelType, 0); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifndef TARGET_OPENGLES glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, (GLint *) &oldFramebuffer); if(numSamples ){ // MULTISAMPLE // //THEO Create the render buffer for depth glGenRenderbuffersEXT(1, &depthBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_DEPTH_COMPONENT, texData.tex_w, texData.tex_h); //THEO multi sampled color buffer glGenRenderbuffersEXT(1, &colorBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, colorBuffer); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, texData.glTypeInternal, texData.tex_w, texData.tex_h); //THEO create fbo for multi sampled content and attach depth and color buffers to it glGenFramebuffersEXT(1, &mfbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mfbo); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, colorBuffer); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer); }else{ //THEO Create the render buffer for depth glGenRenderbuffersEXT(1, &depthBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, texData.tex_w, texData.tex_h); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer); } // create & setup FBO glGenFramebuffersEXT(1, &fbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); // attach it to the FBO so we can render to it glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texData.textureTarget, (GLuint)texData.textureID, 0); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if(status != GL_FRAMEBUFFER_COMPLETE_EXT) { cout<<"glBufferTexture failed to initialize. Perhaps your graphics card doesnt support the framebuffer extension? If you are running osx prior to system 10.5, that could be the cause"<<endl; std::exit(1); } clear(0, 0, 0, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFramebuffer); #else if(numSamples ){ ofLog(OF_LOG_WARNING, "Multi-sampling not supported on OpenGL ES"); }else{ } glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, (GLint *) &oldFramebuffer); // create & setup FBO glGenFramebuffersOES(1, &fbo); glBindFramebufferOES(GL_FRAMEBUFFER_OES, fbo); // attach it to the FBO so we can render to it glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, texData.textureTarget, (GLuint)texData.textureID, 0); glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldFramebuffer); #endif texData.bAllocated = true; }
int FrameBufferObject::CreateImageObject(unsigned int width, unsigned int height, int depthbuffer_enabled, int stencilbuffer_enabled) { //Create the Image object ImageObject new_object; EH_DECLARE; new_object.width = width; new_object.height = height; new_object.texture_type = NULL; new_object.texture_id = NULL; new_object.depth_id = NULL; new_object.stencil_id = NULL; EH_Log("CreateImageObject %d %d\n", width, height); //First determine if the requested dimensions are power of two if (ispoweroftwo(width) && ispoweroftwo(height)) { new_object.texture_type = GL_TEXTURE_2D; //Power of two enum EH_Log("Using GL_TEXTURE_2D"); } else { new_object.texture_type = 0x84F5; //Non power of two enum } //Create texture glGenTextures(1, &new_object.texture_id); glBindTexture(new_object.texture_type, new_object.texture_id); glTexImage2D(new_object.texture_type, 0, GL_RGBA, new_object.width, new_object.height, 0, GL_RGBA, GL_FLOAT, NULL); //GLenum filterMode = (new_object.texture_type == 0x84F5) ? GL_NEAREST : GL_LINEAR; //GLenum filterMode = GL_NEAREST; GLfloat filterMode = GL_LINEAR; glTexParameterf(new_object.texture_type, GL_TEXTURE_MIN_FILTER, filterMode); glTexParameterf(new_object.texture_type, GL_TEXTURE_MAG_FILTER, filterMode); glTexParameterf(new_object.texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);//GL_CLAMP glTexParameterf(new_object.texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);//GL_CLAMP #ifdef OM_MULTISAMPLE if (1) { glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, framebuffer_id); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, 2, GL_RGBA8, new_object.width, new_object.height); CheckFramebufferStatus(); } #endif //Create the depth RenderBuffer if requested if (depthbuffer_enabled != 0) { glGenRenderbuffersEXT(1, &new_object.depth_id); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, new_object.depth_id); #ifdef OM_MULTISAMPLE if (1) { //samples=2, format=GL_DEPTH_COMPONENT24, width=256, height=256 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, 2, GL_DEPTH_COMPONENT16, new_object.width, new_object.height); CheckFramebufferStatus(); } else #endif glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, new_object.width, new_object.height); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer_id); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, new_object.depth_id); //CheckFramebufferStatus(); } //Create the stencil RenderBuffer if requested if (stencilbuffer_enabled != 0) { glGenRenderbuffersEXT(1, &new_object.stencil_id); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, new_object.stencil_id); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, new_object.width, new_object.height); } //Push this new image object onto the list image_objects.push_back(new_object); //Return the 'index' for the id of this texture return (int)image_objects.size() - 1; }
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples) { m_efbFramebuffer = 0; m_efbColor = 0; m_efbDepth = 0; m_resolvedFramebuffer = 0; m_resolvedColorTexture = 0; m_resolvedDepthTexture = 0; m_xfbFramebuffer = 0; m_targetWidth = targetWidth; m_targetHeight = targetHeight; m_msaaSamples = msaaSamples; m_msaaCoverageSamples = msaaCoverageSamples; // The EFB can be set to different pixel formats by the game through the // BPMEM_ZCOMPARE register (which should probably have a different name). // They are: // - 24-bit RGB (8-bit components) with 24-bit Z // - 24-bit RGBA (6-bit components) with 24-bit Z // - Multisampled 16-bit RGB (5-6-5 format) with 16-bit Z // We only use one EFB format here: 32-bit ARGB with 24-bit Z. // Multisampling depends on user settings. // The distinction becomes important for certain operations, i.e. the // alpha channel should be ignored if the EFB does not have one. // Create EFB target. glGenFramebuffersEXT(1, &m_efbFramebuffer); if (m_msaaSamples <= 1) { // EFB targets will be textures in non-MSAA mode. GLuint glObj[2]; glGenTextures(2, glObj); m_efbColor = glObj[0]; m_efbDepth = glObj[1]; glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbColor); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbDepth); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); // Bind target textures to the EFB framebuffer. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbColor, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0); GL_REPORT_FBO_ERROR(); } else { // EFB targets will be renderbuffers in MSAA mode (required by OpenGL). // Resolve targets will be created to transfer EFB to RAM textures. // XFB framebuffer will be created to transfer EFB to XFB texture. // Create EFB target renderbuffers. GLuint glObj[2]; glGenRenderbuffersEXT(2, glObj); m_efbColor = glObj[0]; m_efbDepth = glObj[1]; glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor); if (m_msaaCoverageSamples) glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight); else glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth); if (m_msaaCoverageSamples) glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight); else glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); // Bind target renderbuffers to EFB framebuffer. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_efbColor); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_efbDepth); GL_REPORT_FBO_ERROR(); // Create resolved targets for transferring multisampled EFB to texture. glGenFramebuffersEXT(1, &m_resolvedFramebuffer); glGenTextures(2, glObj); m_resolvedColorTexture = glObj[0]; m_resolvedDepthTexture = glObj[1]; glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); // Bind resolved textures to resolved framebuffer. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_resolvedFramebuffer); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0); GL_REPORT_FBO_ERROR(); // Return to EFB framebuffer. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); } // Create XFB framebuffer; targets will be created elsewhere. glGenFramebuffersEXT(1, &m_xfbFramebuffer); // EFB framebuffer is currently bound, make sure to clear its alpha value to 1.f glViewport(0, 0, m_targetWidth, m_targetHeight); glScissor(0, 0, m_targetWidth, m_targetHeight); glClearColor(0.f, 0.f, 0.f, 1.f); glClearDepth(1.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); }
void CGLFramebufferEXT::Create() { if (m_fbo != 0) return; m_width = m_params.width; m_height = m_params.height; m_depth = m_params.depth; m_samples = m_params.samples; glGenFramebuffersEXT(1, &m_fbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); // create color texture if (m_params.colorTexture) { GLint previous; glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous); glGenTextures(1, &m_colorTexture); glBindTexture(GL_TEXTURE_2D, m_colorTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_params.width, m_params.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBindTexture(GL_TEXTURE_2D, previous); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_colorTexture, 0); } // create color renderbuffer else { glGenRenderbuffersEXT(1, &m_colorRenderbuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_colorRenderbuffer); if (m_params.samples > 1) glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_params.samples, GL_RGBA8, m_params.width, m_params.height); else glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, m_params.width, m_params.height); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_colorRenderbuffer); } GLuint depthFormat = 0; switch (m_params.depth) { case 16: depthFormat = GL_DEPTH_COMPONENT16; break; case 24: depthFormat = GL_DEPTH_COMPONENT24; break; case 32: depthFormat = GL_DEPTH_COMPONENT32; break; default: depthFormat = GL_DEPTH_COMPONENT16; break; } // create depth texture if (m_params.depthTexture) { GLint previous; glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous); glGenTextures(1, &m_depthTexture); glBindTexture(GL_TEXTURE_2D, m_depthTexture); glTexImage2D(GL_TEXTURE_2D, 0, depthFormat, m_params.width, m_params.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); float color[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color); glBindTexture(GL_TEXTURE_2D, previous); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, m_depthTexture, 0); } // create depth renderbuffer else { glGenRenderbuffersEXT(1, &m_depthRenderbuffer); glBindRenderbufferEXT(GL_RENDERBUFFER, m_depthRenderbuffer); if (m_params.samples > 1) glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_params.samples, depthFormat, m_params.width, m_params.height); else glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, depthFormat, m_params.width, m_params.height); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthRenderbuffer); } GLuint result = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (result != GL_FRAMEBUFFER_COMPLETE_EXT) { GetLogger()->Error("Framebuffer incomplete: %d\n", result); assert(false); } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_currentFBO); }
bool CFrameBufferObject::createMSAA( GLuint width, GLuint height, fboConfig *p_config, fboData *p_data ) { GLint query; bool ret = false; // Step #1 { glGenRenderbuffersEXT( 1, &p_data->depthRB ); glGenRenderbuffersEXT( 1, &p_data->colorRB ); glGenFramebuffersEXT ( 1, &p_data->resolveFB ); p_data->depthTex = 0; //no resolve of depth buffer for now //multisample, so we need to resolve from the FBO, bind the texture to the resolve FBO glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, p_data->resolveFB); glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, m_eGLTarget, p_data->colorTex, 0); ret &= checkStatus(__FILE__, __LINE__, true); //now handle the rendering FBO glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, p_data->fb); // initialize color renderbuffer glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, p_data->colorRB); } // Step #2 { // create a regular MSAA color buffer glRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, p_config->depthSamples, p_config->colorFormat, width, height); // check the number of samples glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &query); if ( query < p_config->depthSamples) { ret = false; } else if ( query > p_config->depthSamples) { p_config->depthSamples = query; } } // Step #3 { // attach the multisampled color buffer glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, p_data->colorRB); ret &= checkStatus(__FILE__, __LINE__, true); // bind the multisampled depth buffer glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, p_data->depthRB); } // Step #4 - create the multisampled depth buffer (without coverage sampling) { // create a regular (not coverage sampled) MSAA depth buffer glRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, p_config->depthSamples, p_config->depthFormat, width, height); // check the number of depth samples glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &query); if ( query < p_config->depthSamples) { ret = false; } else if ( query < p_config->depthSamples) { p_config->depthSamples = query; } } return ret; }
void WebGraphicsContext3DDefaultImpl::reshape(int width, int height) { m_cachedWidth = width; m_cachedHeight = height; makeContextCurrent(); GLenum target = GL_TEXTURE_2D; if (!m_texture) { // Generate the texture object m_texture = createTextureObject(target); // Generate the framebuffer object glGenFramebuffersEXT(1, &m_fbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); m_boundFBO = m_fbo; if (m_attributes.depth || m_attributes.stencil) glGenRenderbuffersEXT(1, &m_depthStencilBuffer); // Generate the multisample framebuffer object if (m_attributes.antialias) { glGenFramebuffersEXT(1, &m_multisampleFBO); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); m_boundFBO = m_multisampleFBO; glGenRenderbuffersEXT(1, &m_multisampleColorBuffer); if (m_attributes.depth || m_attributes.stencil) glGenRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer); } } GLint internalColorFormat, colorFormat, internalDepthStencilFormat = 0; if (m_attributes.alpha) { internalColorFormat = GL_RGBA8; colorFormat = GL_RGBA; } else { internalColorFormat = GL_RGB8; colorFormat = GL_RGB; } if (m_attributes.stencil || m_attributes.depth) { // We don't allow the logic where stencil is required and depth is not. // See GraphicsContext3DInternal constructor. if (m_attributes.stencil && m_attributes.depth) internalDepthStencilFormat = GL_DEPTH24_STENCIL8_EXT; else internalDepthStencilFormat = GL_DEPTH_COMPONENT; } bool mustRestoreFBO = false; // Resize multisampling FBO if (m_attributes.antialias) { GLint maxSampleCount; glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSampleCount); GLint sampleCount = std::min(8, maxSampleCount); if (m_boundFBO != m_multisampleFBO) { mustRestoreFBO = true; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); } glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalColorFormat, width, height); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); if (m_attributes.stencil || m_attributes.depth) { glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalDepthStencilFormat, width, height); if (m_attributes.stencil) glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); if (m_attributes.depth) glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); } glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { printf("GraphicsContext3D: multisampling framebuffer was incomplete\n"); // FIXME: cleanup. notImplemented(); } } // Resize regular FBO if (m_boundFBO != m_fbo) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); mustRestoreFBO = true; } glBindTexture(target, m_texture); glTexImage2D(target, 0, internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, m_texture, 0); glBindTexture(target, 0); if (!m_attributes.antialias && (m_attributes.stencil || m_attributes.depth)) { glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthStencilBuffer); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalDepthStencilFormat, width, height); if (m_attributes.stencil) glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); if (m_attributes.depth) glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); } GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { printf("WebGraphicsContext3DDefaultImpl: framebuffer was incomplete\n"); // FIXME: cleanup. notImplemented(); } if (m_attributes.antialias) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); if (m_boundFBO == m_multisampleFBO) mustRestoreFBO = false; } // Initialize renderbuffers to 0. GLboolean colorMask[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}, depthMask = GL_TRUE, stencilMask = GL_TRUE; GLboolean isScissorEnabled = GL_FALSE; GLboolean isDitherEnabled = GL_FALSE; GLbitfield clearMask = GL_COLOR_BUFFER_BIT; glGetBooleanv(GL_COLOR_WRITEMASK, colorMask); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); if (m_attributes.depth) { glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); glDepthMask(GL_TRUE); clearMask |= GL_DEPTH_BUFFER_BIT; } if (m_attributes.stencil) { glGetBooleanv(GL_STENCIL_WRITEMASK, &stencilMask); glStencilMask(GL_TRUE); clearMask |= GL_STENCIL_BUFFER_BIT; } isScissorEnabled = glIsEnabled(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST); isDitherEnabled = glIsEnabled(GL_DITHER); glDisable(GL_DITHER); glClear(clearMask); glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]); if (m_attributes.depth) glDepthMask(depthMask); if (m_attributes.stencil) glStencilMask(stencilMask); if (isScissorEnabled) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); if (isDitherEnabled) glEnable(GL_DITHER); else glDisable(GL_DITHER); if (mustRestoreFBO) glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); #ifdef FLIP_FRAMEBUFFER_VERTICALLY if (m_scanline) { delete[] m_scanline; m_scanline = 0; } m_scanline = new unsigned char[width * 4]; #endif // FLIP_FRAMEBUFFER_VERTICALLY }