/** Detect which internal formats are allowed as RTT Also detect what combinations of stencil and depth are allowed with this internal format. */ void GLES2FBOManager::detectFBOFormats() { // Try all formats, and report which ones work as target GLuint fb, tid; GLenum target = GL_TEXTURE_2D; for(size_t x=0; x<PF_COUNT; ++x) { mProps[x].valid = false; // Fetch GL format token GLint fmt = GLES2PixelUtil::getGLInternalFormat((PixelFormat)x); if((fmt == GL_NONE) && (x != 0)) continue; // No test for compressed formats if(PixelUtil::isCompressed((PixelFormat)x)) continue; // Create and attach framebuffer glGenFramebuffers(1, &fb); glBindFramebuffer(GL_FRAMEBUFFER, fb); if (fmt != GL_NONE) { // Create and attach texture glGenTextures(1, &tid); glBindTexture(target, tid); // Set some default parameters #if GL_APPLE_texture_max_level glTexParameteri(target, GL_TEXTURE_MAX_LEVEL_APPLE, 0); #endif 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); glTexImage2D(target, 0, fmt, PROBE_SIZE, PROBE_SIZE, 0, fmt, GLES2PixelUtil::getGLOriginDataType((PixelFormat)x), 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, tid, 0); } // Check status GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER); // Ignore status in case of fmt==GL_NONE, because no implementation will accept // a buffer without *any* attachment. Buffers with only stencil and depth attachment // might still be supported, so we must continue probing. if(fmt == GL_NONE || status == GL_FRAMEBUFFER_COMPLETE) { mProps[x].valid = true; StringUtil::StrStreamType str; str << "FBO " << PixelUtil::getFormatName((PixelFormat)x) << " depth/stencil support: "; // For each depth/stencil formats for (size_t depth = 0; depth < DEPTHFORMAT_COUNT; ++depth) { #if GL_OES_packed_depth_stencil if (depthFormats[depth] != GL_DEPTH24_STENCIL8_OES) { // General depth/stencil combination for (size_t stencil = 0; stencil < STENCILFORMAT_COUNT; ++stencil) { // StringUtil::StrStreamType l; // l << "Trying " << PixelUtil::getFormatName((PixelFormat)x) // << " D" << depthBits[depth] // << "S" << stencilBits[stencil]; // LogManager::getSingleton().logMessage(l.str()); if (_tryFormat(depthFormats[depth], stencilFormats[stencil])) { /// Add mode to allowed modes str << "D" << depthBits[depth] << "S" << stencilBits[stencil] << " "; FormatProperties::Mode mode; mode.depth = depth; mode.stencil = stencil; mProps[x].modes.push_back(mode); } } } else #endif { // Packed depth/stencil format if (_tryPackedFormat(depthFormats[depth])) { /// Add mode to allowed modes str << "Packed-D" << depthBits[depth] << "S" << 8 << " "; FormatProperties::Mode mode; mode.depth = depth; mode.stencil = 0; // unuse mProps[x].modes.push_back(mode); } } } LogManager::getSingleton().logMessage(str.str()); } // Delete texture and framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fb); if (fmt!=GL_NONE) glDeleteTextures(1, &tid); } // Clear any errors GL_CHECK_ERROR; String fmtstring; for(size_t x=0; x<PF_COUNT; ++x) { if(mProps[x].valid) fmtstring += PixelUtil::getFormatName((PixelFormat)x)+" "; } LogManager::getSingleton().logMessage("[GLES2] : Valid FBO targets " + fmtstring); }
/** Detect which internal formats are allowed as RTT Also detect what combinations of stencil and depth are allowed with this internal format. */ void GLFBOManager::detectFBOFormats() { // Try all formats, and report which ones work as target GLuint fb = 0, tid = 0; GLint old_drawbuffer = 0, old_readbuffer = 0; GLenum target = GL_TEXTURE_2D; glGetIntegerv (GL_DRAW_BUFFER, &old_drawbuffer); glGetIntegerv (GL_READ_BUFFER, &old_readbuffer); for(size_t x=0; x<PF_COUNT; ++x) { mProps[x].valid = false; // Fetch GL format token GLenum fmt = GLPixelUtil::getGLInternalFormat((PixelFormat)x); if(fmt == GL_NONE && x!=0) continue; // No test for compressed formats if(PixelUtil::isCompressed((PixelFormat)x)) continue; // Buggy ATI cards *crash* on non-RGB(A) formats int depths[4]; PixelUtil::getBitDepths((PixelFormat)x, depths); if(fmt!=GL_NONE && mATIMode && (!depths[0] || !depths[1] || !depths[2])) continue; // Create and attach framebuffer glGenFramebuffersEXT(1, &fb); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb); if (fmt!=GL_NONE) { // Create and attach texture glGenTextures(1, &tid); glBindTexture(target, tid); // Set some default parameters so it won't fail on NVidia cards if (GLEW_VERSION_1_2) glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0); 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); glTexImage2D(target, 0, fmt, PROBE_SIZE, PROBE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, tid, 0); } else { // Draw to nowhere -- stencil/depth only glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); } // Check status GLuint status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); // Ignore status in case of fmt==GL_NONE, because no implementation will accept // a buffer without *any* attachment. Buffers with only stencil and depth attachment // might still be supported, so we must continue probing. if(fmt == GL_NONE || status == GL_FRAMEBUFFER_COMPLETE_EXT) { mProps[x].valid = true; StringUtil::StrStreamType str; str << "FBO " << PixelUtil::getFormatName((PixelFormat)x) << " depth/stencil support: "; // For each depth/stencil formats for (size_t depth = 0; depth < DEPTHFORMAT_COUNT; ++depth) { if (depthFormats[depth] != GL_DEPTH24_STENCIL8_EXT) { // General depth/stencil combination for (size_t stencil = 0; stencil < STENCILFORMAT_COUNT; ++stencil) { //StringUtil::StrStreamType l; //l << "Trying " << PixelUtil::getFormatName((PixelFormat)x) // << " D" << depthBits[depth] // << "S" << stencilBits[stencil]; //LogManager::getSingleton().logMessage(l.str()); if (_tryFormat(depthFormats[depth], stencilFormats[stencil])) { /// Add mode to allowed modes str << "D" << depthBits[depth] << "S" << stencilBits[stencil] << " "; FormatProperties::Mode mode; mode.depth = depth; mode.stencil = stencil; mProps[x].modes.push_back(mode); } } } else { // Packed depth/stencil format // #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX // It now seems as if this workaround now *breaks* nvidia cards on Linux with the 169.12 drivers on Linux #if 0 // Only query packed depth/stencil formats for 32-bit // non-floating point formats (ie not R32!) // Linux nVidia driver segfaults if you query others if (PixelUtil::getNumElemBits((PixelFormat)x) != 32 || PixelUtil::isFloatingPoint((PixelFormat)x)) { continue; } #endif if (_tryPackedFormat(depthFormats[depth])) { /// Add mode to allowed modes str << "Packed-D" << depthBits[depth] << "S" << 8 << " "; FormatProperties::Mode mode; mode.depth = depth; mode.stencil = 0; // unuse mProps[x].modes.push_back(mode); } } } LogManager::getSingleton().logMessage(str.str()); } // Delete texture and framebuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &fb); // Workaround for NVIDIA / Linux 169.21 driver problem // see http://www.ogre3d.org/phpBB2/viewtopic.php?t=38037&start=25 glFinish(); if (fmt!=GL_NONE) glDeleteTextures(1, &tid); } // It seems a bug in nVidia driver: glBindFramebufferEXT should restore // draw and read buffers, but in some unclear circumstances it won't. glDrawBuffer(old_drawbuffer); glReadBuffer(old_readbuffer); String fmtstring = ""; for(size_t x=0; x<PF_COUNT; ++x) { if(mProps[x].valid) fmtstring += PixelUtil::getFormatName((PixelFormat)x)+" "; } LogManager::getSingleton().logMessage("[GL] : Valid FBO targets " + fmtstring); }
/** Detect which internal formats are allowed as RTT Also detect what combinations of stencil and depth are allowed with this internal format. */ void GLES2FBOManager::detectFBOFormats() { #if OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN memset(mProps, 0, sizeof(mProps)); // TODO: Fix that probing all formats slows down startup not just on the web also on Android / iOS mProps[PF_A8B8G8R8].valid = true; FormatProperties::Mode mode = {1, 0}; mProps[PF_A8B8G8R8].modes.push_back(mode); LogManager::getSingleton().logMessage("[GLES2] : detectFBOFormats is disabled on this platform (due performance reasons)"); #else // Try all formats, and report which ones work as target GLES2RenderSystem* rs = getGLES2RenderSystem(); GLuint fb = 0, tid = 0; bool hasGLES3 = rs->hasMinGLVersion(3, 0); const size_t depthCount = hasGLES3 ? DEPTHFORMAT_COUNT : DEPTHFORMAT_COUNT - 1; // 32_8 is not available on GLES2 const size_t stencilStep = hasGLES3 ? 3 : 1; // 1 and 4 bit not available on GLES3 for(size_t x = 0; x < PF_COUNT; ++x) { mProps[x].valid = false; // Fetch GL format token GLint internalFormat = GLES2PixelUtil::getGLInternalFormat((PixelFormat)x); GLenum fmt = GLES2PixelUtil::getGLOriginFormat((PixelFormat)x); GLenum type = GLES2PixelUtil::getGLOriginDataType((PixelFormat)x); // Note: letting PF_UNKNOWN pass here is for pure depth/ stencil formats // however there are reports that this crashes some unspecified android devices if((internalFormat == GL_NONE || fmt == GL_NONE || type == GL_NONE) && (x != 0)) continue; // not color-renderable in GLES if(fmt == GL_BGRA_EXT) continue; // No test for compressed formats if(PixelUtil::isCompressed((PixelFormat)x)) continue; // Create and attach framebuffer _createTempFramebuffer((PixelFormat)x, internalFormat, fmt, type, fb, tid); // Ignore status in case of fmt==GL_NONE, because no implementation will accept // a buffer without *any* attachment. Buffers with only stencil and depth attachment // might still be supported, so we must continue probing. if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) { mProps[x].valid = true; StringStream str; str << "FBO " << PixelUtil::getFormatName((PixelFormat)x) << " depth/stencil support: "; // For each depth/stencil formats for (size_t depth = 0; depth < depthCount; ++depth) { if (depthFormats[depth] != GL_DEPTH24_STENCIL8 && depthFormats[depth] != GL_DEPTH32F_STENCIL8) { // General depth/stencil combination for (size_t stencil = 0; stencil < STENCILFORMAT_COUNT; stencil += stencilStep) { // StringStream l; // l << "Trying " << PixelUtil::getFormatName((PixelFormat)x) // << " D" << depthBits[depth] // << "S" << stencilBits[stencil]; // LogManager::getSingleton().logMessage(l.str()); if (_tryFormat(depthFormats[depth], stencilFormats[stencil])) { // Add mode to allowed modes str << "D" << depthBits[depth] << "S" << stencilBits[stencil] << " "; FormatProperties::Mode mode; mode.depth = depth; mode.stencil = stencil; mProps[x].modes.push_back(mode); } else { // There is a small edge case that FBO is trashed during the test // on some drivers resulting in undefined behavior glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fb); _createTempFramebuffer((PixelFormat)x, internalFormat, fmt, type, fb, tid); } } } else if(hasGLES3 || rs->checkExtension("GL_OES_packed_depth_stencil") ) { // Packed depth/stencil format if (_tryPackedFormat(depthFormats[depth])) { // Add mode to allowed modes str << "Packed-D" << depthBits[depth] << "S" << 8 << " "; FormatProperties::Mode mode; mode.depth = depth; mode.stencil = 0; // unuse mProps[x].modes.push_back(mode); } else { // There is a small edge case that FBO is trashed during the test // on some drivers resulting in undefined behavior glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fb); _createTempFramebuffer((PixelFormat)x, internalFormat, fmt, type, fb, tid); } } } LogManager::getSingleton().logMessage(str.str()); } // Delete texture and framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fb); if (internalFormat != GL_NONE) { glDeleteTextures(1, &tid); tid = 0; } } // Clear any errors glGetError(); #endif String fmtstring; for(size_t x = 0; x < PF_COUNT; ++x) { if(mProps[x].valid) fmtstring += PixelUtil::getFormatName((PixelFormat)x)+" "; } LogManager::getSingleton().logMessage("[GLES2] : Valid FBO targets " + fmtstring); }