void GLES11RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, uint32_t* status, bool useReadPixels, int reqWidth, int reqHeight) { GLuint tname, name; if (!useReadPixels) { // turn our EGLImage into a texture glGenTextures(1, &tname); glBindTexture(GL_TEXTURE_2D, tname); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); // create a Framebuffer Object to render into glGenFramebuffersOES(1, &name); glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); } else { // since we're going to use glReadPixels() anyways, // use an intermediate renderbuffer instead glGenRenderbuffersOES(1, &tname); glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname); glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, reqWidth, reqHeight); // create a FBO to render into glGenFramebuffersOES(1, &name); glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname); } *status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); *texName = tname; *fbName = name; }
/** Try a certain packed depth/stencil format, and return the status. @returns true if this combo is supported false if this combo is not supported */ bool GLESFBOManager::_tryPackedFormat(GLenum packedFormat) { GLuint packedRB; /// Generate renderbuffer glGenRenderbuffersOES(1, &packedRB); /// Bind it to FBO glBindRenderbufferOES(GL_RENDERBUFFER_OES, packedRB); /// Allocate storage for buffer glRenderbufferStorageOES(GL_RENDERBUFFER_OES, packedFormat, PROBE_SIZE, PROBE_SIZE); /// Attach depth glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, packedRB); /// Attach stencil glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, packedRB); GLuint status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); /// Detach and destroy glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, 0); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, 0); glDeleteRenderbuffersOES(1, &packedRB); return status == GL_FRAMEBUFFER_COMPLETE_OES; }
// src서피스를 this로 카피. void XSurfaceOpenGL::CopySurface( XSurface *src ) { XSurfaceOpenGL *pSrc = (XSurfaceOpenGL *)src; // src를 FBO에 연결 // glCopyTexImage를 이용해 src에서 this로 옮김. GLuint fbo; glGenFramebuffersOES(1, &fbo); glBindFramebufferOES(GL_FRAMEBUFFER_OES, fbo); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, pSrc->GetTextureID(), 0); GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); if( status != GL_FRAMEBUFFER_COMPLETE_OES ) { XLOG( "status=%d", status ); return; } // copy texture from framebuffer glBindTexture(GL_TEXTURE_2D, m_textureID); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, pSrc->GetMemWidth(), pSrc->GetMemHeight()); // FBO해제 GRAPHICS_GL->RestoreFrameBuffer(); glDeleteFramebuffersOES(1, &fbo); }
inline GLenum VL_glCheckFramebufferStatus(GLenum target) { if (glCheckFramebufferStatusOES) return glCheckFramebufferStatusOES(target); else VL_TRAP(); return GL_FRAMEBUFFER_UNSUPPORTED; }
extern void hdglDeleteTextureFrameBuffer(const GLuint fbo) { #ifndef LEVEL_EDITOR GLuint status; glDeleteFramebuffersOES(1, &fbo); status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); #endif }
/** Try a certain FBO format, and return the status. Also sets mDepthRB and mStencilRB. @returns true if this combo is supported false if this combo is not supported */ GLuint GLESFBOManager::_tryFormat(GLenum depthFormat, GLenum stencilFormat) { GLuint status, depthRB = 0, stencilRB = 0; if(depthFormat != GL_NONE) { /// Generate depth renderbuffer glGenRenderbuffersOES(1, &depthRB); /// Bind it to FBO glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRB); /// Allocate storage for depth buffer glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthFormat, PROBE_SIZE, PROBE_SIZE); /// Attach depth glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRB); } // Stencil buffers aren't available on iPhone if(stencilFormat != GL_NONE) { /// Generate stencil renderbuffer glGenRenderbuffersOES(1, &stencilRB); /// Bind it to FBO glBindRenderbufferOES(GL_RENDERBUFFER_OES, stencilRB); /// Allocate storage for stencil buffer glRenderbufferStorageOES(GL_RENDERBUFFER_OES, stencilFormat, PROBE_SIZE, PROBE_SIZE); /// Attach stencil glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, stencilRB); } status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); /// If status is negative, clean up // Detach and destroy glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, 0); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, 0); if (depthRB) glDeleteRenderbuffersOES(1, &depthRB); if (stencilRB) glDeleteRenderbuffersOES(1, &stencilRB); return status == GL_FRAMEBUFFER_COMPLETE_OES; }
void GLES11RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, uint32_t* status) { GLuint tname, name; // turn our EGLImage into a texture glGenTextures(1, &tname); glBindTexture(GL_TEXTURE_2D, tname); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); // create a Framebuffer Object to render into glGenFramebuffersOES(1, &name); glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); *status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); *texName = tname; *fbName = name; }
FBO *createFBO(s32 width, s32 height, bool hd) { // save current FBO FBO *oldFBO = getFBOUsed(); GLuint framebuffer; GLuint depthRenderbuffer; width = width; height = height; s32 texturePtrId = createTexture(0, 0); setTexture(texturePtrId, width, height, 3, NULL); Texture *tex = getTexture(texturePtrId); // create depth renderbuffer glGenRenderbuffersOES(1, &depthRenderbuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer); glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, width, height); // bind framebuffer & attach texture glGenFramebuffersOES(1, &framebuffer); glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tex->mTextureId, 0); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer); // check binding if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { logError(TAG, "CRITICAL ERROR: FBO no complete"); return 0; } // save info into structure FBO *fbo = (FBO *)malloc(sizeof(FBO)); fbo->mFBO = framebuffer; fbo->mWidth = width; fbo->mHeight = height; fbo->mTexturePtrId = texturePtrId; fbo->mDepthRenderBuffer = depthRenderbuffer; // restore FBO useFBO(oldFBO); return fbo; }
extern int hdglGenTextureFrameBuffer(const hdTexture *texture) { GLuint fbo, status; glGenFramebuffersOES(1, &fbo); glBindFramebufferOES(GL_FRAMEBUFFER_OES, fbo); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, texture->texnum, 0); status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); if (status != GL_FRAMEBUFFER_COMPLETE_OES) { hdPrintf("Could not create frame buffer."); return -1; } else { return fbo; } }
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height) { // get currently bound fbo to reset to it later GLint current_fbo; glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, ¤t_fbo); // generate depth buffer glGenRenderbuffersOES(1, &depthbuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthbuffer); glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, width, height); glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0); // generate texture save target glGenTextures(1, &img); glBindTexture(GL_TEXTURE_2D, img); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8_OES, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, 0); // create framebuffer glGenFramebuffersOES(1, &framebuffer); glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, img, 0); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthbuffer); GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); // unbind framebuffer glBindFramebufferOES(GL_FRAMEBUFFER_OES, (GLuint)current_fbo); return status; }
bool CCGrabber::activateFBO(RenderContext* ctx, CCTexture2D *pTexture) { bool valid = m_FrameBuffer->isValid(ctx); if (valid && m_BoundTexture == pTexture) return true; if (!valid) { // generate FBO if (!m_FrameBuffer->generate(ctx)) return false; // device not ready } m_BoundTexture = pTexture; if (pTexture == NULL) return false; glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &m_oldFBO); // bind glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_FrameBuffer->useHandle(ctx)); // associate texture with FBO glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, pTexture->activate(ctx), 0); // check if it worked CCAssert(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) == GL_FRAMEBUFFER_COMPLETE_OES, "Frame Grabber: Could not attach texture to framebuffer"); glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_oldFBO); return true; }
/** Detect which internal formats are allowed as RTT Also detect what combinations of stencil and depth are allowed with this internal format. */ void GLESFBOManager::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 GLenum fmt = GLESPixelUtil::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 glGenFramebuffersOES(1, &fb); glBindFramebufferOES(GL_FRAMEBUFFER_OES, fb); if (fmt!=GL_NONE) { // Create and attach texture glGenTextures(1, &tid); glBindTexture(target, tid); // Set some default parameters glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_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, GL_UNSIGNED_BYTE, 0); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, target, tid, 0); } // Check status GLuint status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); // 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_OES) { 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_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 { // 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 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); glDeleteFramebuffersOES(1, &fb); if (fmt!=GL_NONE) glDeleteTextures(1, &tid); } String fmtstring; for(size_t x=0; x<PF_COUNT; ++x) { if(mProps[x].valid) fmtstring += PixelUtil::getFormatName((PixelFormat)x)+" "; } LogManager::getSingleton().logMessage("[GLES] : Valid FBO targets " + fmtstring); }
int createFrameBuffer(AndroidContext *rc) { int backingWidth; int backingHeight; int res; if ( rc->framebuff >= 0 ) releaseFrameBuffer(rc); LOG( ANDROID_LOG_DEBUG, TAG, "Android Create FrameBuffer")); glGenFramebuffersOES(1, &(rc->framebuff)); glBindFramebufferOES(GL_FRAMEBUFFER_OES, rc->framebuff); // glGenRenderbuffersOES(1, &(rc->depthbuff)); // glBindRenderbufferOES(GL_RENDERBUFFER_OES, rc->depthbuff); // glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); // glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); // LOG( ANDROID_LOG_ERROR, TAG, "Android Depth Buffer Size: %dx%d\n", backingWidth, backingHeight)); // glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, rc->width, rc->height); // glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, // GL_RENDERBUFFER_OES, rc->depthbuff); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, rc->texID, 0); if ( (res=(int)glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)) != GL_FRAMEBUFFER_COMPLETE_OES ) { LOG( ANDROID_LOG_ERROR, TAG, "Android failed to make complete framebuffer object:"); switch (res) { case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES: LOG( ANDROID_LOG_ERROR, TAG, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES"); break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES: LOG( ANDROID_LOG_ERROR, TAG, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES"); break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES: LOG( ANDROID_LOG_ERROR, TAG, "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES"); break; case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES: LOG( ANDROID_LOG_ERROR, TAG, "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES"); break; case GL_FRAMEBUFFER_UNSUPPORTED_OES: LOG( ANDROID_LOG_ERROR, TAG, "GL_FRAMEBUFFER_UNSUPPORTED_OES"); break; default : LOG( ANDROID_LOG_ERROR, TAG, "Unknown error: %d", res); break; } return 1; } //glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); return 0; }
GLenum glCheckFramebufferStatusOESLogged(GLenum target) { printf("glCheckFramebufferStatusOES(%s)\n", GLEnumName(target)); return glCheckFramebufferStatusOES(target); }
void TextureGPU::createDrawableIntoColorTextureWithDepth(PrimitiveTypes::UInt32 w, PrimitiveTypes::UInt32 h, ESamplerState sampler, bool use32BitRedForDepth /* = false*/) { StringOps::writeToString("createDrawableIntoColorTextureWithDepth", m_name, 256); m_samplerState = sampler; # if APIABSTRACTION_D3D9 D3D9Renderer *pD3D9Renderer = static_cast<D3D9Renderer *>(m_pContext->getGPUScreen()); LPDIRECT3DDEVICE9 pDevice = pD3D9Renderer->m_pD3D9Device; m_viewport.X = 0; m_viewport.Y = 0; m_viewport.Width = w; m_viewport.Height = h; m_viewport.MinZ = 0.0f; m_viewport.MaxZ = 1.0f; #if APIABSTRACTION_X360 HRESULT hr = D3DXCreateTexture(pDevice, w, h, 1, D3DUSAGE_RENDERTARGET, use32BitRedForDepth ? D3DFMT_R32F : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &this->m_pTexture ); #else HRESULT hr = pDevice->CreateTexture( w, h, 1, D3DUSAGE_RENDERTARGET, use32BitRedForDepth ? D3DFMT_R32F : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &this->m_pTexture, NULL); #endif D3DSURFACE_DESC desc; m_pTexture->GetSurfaceLevel( 0, &m_pSurface ); m_pSurface->GetDesc( &desc ); #ifdef _XBOX //create depth stencil surface to use with this texture hr = pDevice->CreateDepthStencilSurface( w, h, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, // multi sample quality TRUE, // Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. //If this flag is set, the contents of the depth stencil buffer will be invalid // after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface. &m_pEDRamDSRenderTargetSurface, NULL); assert(SUCCEEDED(hr)); hr = pDevice->CreateRenderTarget( desc.Width, desc.Height, ( D3DFORMAT )MAKESRGBFMT( desc.Format ), D3DMULTISAMPLE_NONE, 0, 0, &m_pEDRamColorRenderTargetSurface, NULL ); #else #if D3D9_USE_RENDER_TO_SURFACE hr = D3DXCreateRenderToSurface(pDevice, desc.Width, desc.Height, desc.Format, TRUE, D3DFMT_D16, &m_pRenderToSurface ); #else //create depth stencil surface to use with this texture hr = pDevice->CreateDepthStencilSurface( w, h, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, // multi sample quality TRUE, // Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. //If this flag is set, the contents of the depth stencil buffer will be invalid // after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface. &m_pDSSurface, NULL); #endif #endif assert(SUCCEEDED(hr)); #elif APIABSTRACTION_OGL SamplerState &ss = SamplerStateManager::getInstance()->getSamplerState(m_samplerState); GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); IRenderer::checkForErrors("glTexImage2D"); #if PE_PLAT_IS_IOS PEWARN("We are creating depth texture as 32 bit, because I could not get 16 bit depth working. If you figure it out, change it to 16 bit for better perf (hopefully!)"); #endif glTexImage2D( GL_TEXTURE_2D, // Target 0, // Mip-level #if PE_PLAT_IS_IOS GL_DEPTH_COMPONENT, // InternalFormat #else GL_DEPTH_COMPONENT16, #endif w, // width size h, // height size 0, // border GL_DEPTH_COMPONENT, // input pixel format #if PE_PLAT_IS_IOS GL_UNSIGNED_INT, // input pixel type #else GL_UNSIGNED_SHORT, #endif NULL); // input pixels IRenderer::checkForErrors("glTexImage2D"); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, ss.val_GL_TEXTURE_MIN_FILTER); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, ss.val_GL_TEXTURE_MAG_FILTER); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, ss.val_GL_TEXTURE_WRAP_S); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, ss.val_GL_TEXTURE_WRAP_T); #if !APIABSTRACTION_IOS glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,0); //only one mip // depth related comparison functions glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); #endif glBindTexture(GL_TEXTURE_2D, 0); #if APIABSTRACTION_PS3 glGenFramebuffersOES(1, &m_frameBufferObject); #else glGenFramebuffers(1, &m_frameBufferObject); #endif #if APIABSTRACTION_PS3 glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_frameBufferObject); //set framebuffer for reading and writing. could also use GL_READ_FRAMEBUFFER to set a buffer for reading vs writing. #else glBindFramebuffer(GL_FRAMEBUFFER, m_frameBufferObject); //set framebuffer for reading and writing. could also use GL_READ_FRAMEBUFFER to set a buffer for reading vs writing. #endif //glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, w); / no need for this, since it take size of the texture passed #if APIABSTRACTION_PS3 glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_TEXTURE_2D, texture, 0); #else glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture, 0); #endif m_viewport.x = 0; m_viewport.y = 0; m_viewport.w = w; m_viewport.h = h; m_viewport.minDepth = 0; m_viewport.maxDepth = 1.0f; // had to comment out this assert becasue apparently with newest hardware it is actually complete too //assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE); // make sure API requires color texture too // need to cerate color texture too, otherwise framebuffer object is incomplete glGenTextures(1, &m_texture); glBindTexture(GL_TEXTURE_2D, m_texture); IRenderer::checkForErrors("glTexImage2D"); #if PE_PLAT_IS_IOS if (use32BitRedForDepth) PEWARN("We are creating depth+color and storing dpeth in color. for ios we store it as rgba, since we cant store it as 32bit red.."); #endif glTexImage2D( GL_TEXTURE_2D, // Target 0, // Mip-level #if defined(SN_TARGET_PS3) use32BitRedForDepth ? GL_LUMINANCE32F_ARB : GL_ARGB_SCE, #else #if APIABSTRACTION_IOS use32BitRedForDepth ? GL_RGBA : GL_RGBA, // InternalFormat, for ps3 use GL_ARGB_SCE, why? #else use32BitRedForDepth ? GL_R32F : GL_RGBA, // InternalFormat, for ps3 use GL_ARGB_SCE, why? #endif #endif w, // width size h, // height size 0, // border GL_RGBA, // input pixel format GL_UNSIGNED_BYTE, // input pixel type NULL); // input pixels IRenderer::checkForErrors("glTexImage2D"); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, ss.val_GL_TEXTURE_MIN_FILTER); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, ss.val_GL_TEXTURE_MAG_FILTER); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, ss.val_GL_TEXTURE_WRAP_S); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, ss.val_GL_TEXTURE_WRAP_T); #if !APIABSTRACTION_IOS glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,0); //only one mip #endif //depth related //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_MODE_ARB,GL_COMPARE_R_TO_TEXTURE_ARB); //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); glBindTexture(GL_TEXTURE_2D, 0); #if APIABSTRACTION_PS3 glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); #else glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0); #endif #if !APIABSTRACTION_IOS #if APIABSTRACTION_PS3 assert(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) == GL_FRAMEBUFFER_COMPLETE_OES); #else assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); #endif #endif IRenderer::checkRenderBufferComplete(); #if APIABSTRACTION_PS3 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); // back to default #else glBindFramebuffer(GL_FRAMEBUFFER, 0); // back to default #endif #elif APIABSTRACTION_D3D11 m_viewport.TopLeftX = 0; m_viewport.TopLeftY = 0; m_viewport.Width = w; m_viewport.Height = h; m_viewport.MinDepth = 0.0f; m_viewport.MaxDepth = 1.0f; D3D11Renderer *pD3D11Renderer = static_cast<D3D11Renderer *>(m_pContext->getGPUScreen()); ID3D11Device *pDevice = pD3D11Renderer->m_pD3DDevice; ID3D11DeviceContext *pDeviceContext = pD3D11Renderer->m_pD3DContext; //ID3D11Texture2D *pColorMap = 0; D3D11_TEXTURE2D_DESC texDesc; texDesc.Width = w; texDesc.Height = h; texDesc.MipLevels = 1; texDesc.ArraySize = 1; texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texDesc.SampleDesc.Count = 1; texDesc.SampleDesc.Quality = 0; texDesc.Usage = D3D11_USAGE_DEFAULT; texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; texDesc.CPUAccessFlags = 0; texDesc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS; HRESULT hr = pDevice->CreateTexture2D(&texDesc, 0, &m_pTexture); assert(SUCCEEDED(hr)); // Null description means to create a view to all mipmap levels // using the format the texture was created with hr = pDevice->CreateRenderTargetView(m_pTexture, 0, &m_pRenderTargetView); assert(SUCCEEDED(hr)); hr = pDevice->CreateShaderResourceView(m_pTexture, 0, &m_pShaderResourceView); assert(SUCCEEDED(hr)); // Now create depth part fo the texture ID3D11Texture2D *pDepthMap = 0; texDesc.Format = DXGI_FORMAT_R32_TYPELESS; texDesc.Usage = D3D11_USAGE_DEFAULT; texDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; texDesc.CPUAccessFlags = 0; texDesc.MiscFlags = 0; hr = pDevice->CreateTexture2D(&texDesc, 0, &pDepthMap); assert(SUCCEEDED(hr)); // setting up view for rendering into depth buffer/and reading (stenciling) from it (z-buffer algorithm red/write) D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; dsvDesc.Format = DXGI_FORMAT_D32_FLOAT; dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; dsvDesc.Texture2D.MipSlice = 0; dsvDesc.Flags = 0;//D3D11_DSV_READ_ONLY_DEPTH; hr = pDevice->CreateDepthStencilView(pDepthMap, &dsvDesc, &m_DepthStencilView); assert(SUCCEEDED(hr)); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; srvDesc.Format = DXGI_FORMAT_R32_FLOAT; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MipLevels = texDesc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; hr = pDevice->CreateShaderResourceView(pDepthMap, &srvDesc, &m_pDepthShaderResourceView); assert(SUCCEEDED(hr)); pDepthMap->Release(); #endif }
status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, sp<IMemoryHeap>* heap, uint32_t* w, uint32_t* h, PixelFormat* f, uint32_t sw, uint32_t sh) { LOGI("captureScreenImplLocked"); status_t result = PERMISSION_DENIED; // only one display supported for now if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) return BAD_VALUE; if (!GLExtensions::getInstance().haveFramebufferObject()) return INVALID_OPERATION; // get screen geometry const DisplayHardware& hw(graphicPlane(dpy).displayHardware()); const uint32_t hw_w = hw.getWidth(); const uint32_t hw_h = hw.getHeight(); if ((sw > hw_w) || (sh > hw_h)) return BAD_VALUE; sw = (!sw) ? hw_w : sw; sh = (!sh) ? hw_h : sh; const size_t size = sw * sh * 4; // make sure to clear all GL error flags while ( glGetError() != GL_NO_ERROR ) ; // create a FBO GLuint name, tname; glGenRenderbuffersOES(1, &tname); glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname); glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, sw, sh); glGenFramebuffersOES(1, &name); glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname); GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); if (status == GL_FRAMEBUFFER_COMPLETE_OES) { // invert everything, b/c glReadPixel() below will invert the FB glViewport(0, 0, sw, sh); glScissor(0, 0, sw, sh); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrthof(0, hw_w, 0, hw_h, 0, 1); glMatrixMode(GL_MODELVIEW); // redraw the screen entirely... glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); const size_t count = layers.size(); for (size_t i=0 ; i<count ; ++i) { const sp<LayerBase>& layer(layers[i]); layer->drawForSreenShot(); } // XXX: this is needed on tegra glScissor(0, 0, sw, sh); // check for errors and return screen capture if (glGetError() != GL_NO_ERROR) { // error while rendering result = INVALID_OPERATION; } else { // allocate shared memory large enough to hold the // screen capture sp<MemoryHeapBase> base( new MemoryHeapBase(size, 0, "screen-capture") ); void* const ptr = base->getBase(); if (ptr) { // capture the screen with glReadPixels() glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr); if (glGetError() == GL_NO_ERROR) { *heap = base; *w = sw; *h = sh; *f = PIXEL_FORMAT_RGBA_8888; result = NO_ERROR; } } else { result = NO_MEMORY; } } glEnable(GL_SCISSOR_TEST); glViewport(0, 0, hw_w, hw_h); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } else { result = BAD_VALUE; } // release FBO resources glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); glDeleteRenderbuffersOES(1, &tname); glDeleteFramebuffersOES(1, &name); hw.compositionComplete(); return result; }
void TextureGPU::createDrawableIntoColorTexture(PrimitiveTypes::UInt32 w, PrimitiveTypes::UInt32 h, ESamplerState sampler) { m_samplerState = sampler; StringOps::writeToString("DrawableIntoColorTexture", m_name, 256); # if APIABSTRACTION_D3D9 D3D9Renderer *pD3D9Renderer = static_cast<D3D9Renderer *>(m_pContext->getGPUScreen()); LPDIRECT3DDEVICE9 pDevice = pD3D9Renderer->m_pD3D9Device; m_viewport.X = 0; m_viewport.Y = 0; m_viewport.Width = w; m_viewport.Height = h; m_viewport.MinZ = 0.0f; m_viewport.MaxZ = 1.0f; IDirect3DTexture9 *pColorMap = 0; #if APIABSTRACTION_X360 HRESULT hr = D3DXCreateTexture( pDevice, w, h, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &this->m_pTexture ); #else HRESULT hr = pDevice->CreateTexture( w, h, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &this->m_pTexture, NULL); #endif D3DSURFACE_DESC desc; m_pTexture->GetSurfaceLevel( 0, &m_pSurface ); m_pSurface->GetDesc( &desc ); #ifdef _XBOX hr = pDevice->CreateRenderTarget(desc.Width, desc.Height, ( D3DFORMAT )MAKESRGBFMT( desc.Format ), D3DMULTISAMPLE_NONE, 0, 0, &m_pEDRamColorRenderTargetSurface, NULL ); #else #if D3D9_USE_RENDER_TO_SURFACE hr = D3DXCreateRenderToSurface(pDevice, desc.Width, desc.Height, desc.Format, false, D3DFMT_UNKNOWN, &m_pRenderToSurface ); #endif #endif assert(SUCCEEDED(hr)); #elif APIABSTRACTION_OGL glGenTextures(1, &m_texture); glBindTexture(GL_TEXTURE_2D, m_texture); IRenderer::checkForErrors("glTexImage2D"); glTexImage2D( GL_TEXTURE_2D, // Target 0, // Mip-level #if defined(SN_TARGET_PS3) GL_ARGB_SCE, #else GL_RGBA, // InternalFormat, for ps3 use GL_ARGB_SCE, why? #endif w, // width size h, // height size 0, // border GL_RGBA, // input pixel format GL_UNSIGNED_BYTE, // input pixel type NULL); // input pixels IRenderer::checkForErrors("glTexImage2D"); SamplerState &ss = SamplerStateManager::getInstance()->getSamplerState(m_samplerState); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, ss.val_GL_TEXTURE_MIN_FILTER); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, ss.val_GL_TEXTURE_MAG_FILTER); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, ss.val_GL_TEXTURE_WRAP_S); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, ss.val_GL_TEXTURE_WRAP_T); #if !APIABSTRACTION_IOS glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,0); //only one mip #endif //depth related //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_MODE_ARB,GL_COMPARE_R_TO_TEXTURE_ARB); //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); glBindTexture(GL_TEXTURE_2D, 0); #if APIABSTRACTION_PS3 glGenFramebuffersOES(1, &m_frameBufferObject); #else glGenFramebuffers(1, &m_frameBufferObject); #endif #if APIABSTRACTION_PS3 glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_frameBufferObject); //set framebuffer for reading and writing. could also use GL_READ_FRAMEBUFFER to set a buffer for reading vs writing. #else glBindFramebuffer(GL_FRAMEBUFFER, m_frameBufferObject); //set framebuffer for reading and writing. could also use GL_READ_FRAMEBUFFER to set a buffer for reading vs writing. #endif //glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, w); / no need for this, since it take size of the texture passed #if APIABSTRACTION_PS3 glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); #else glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0); #endif m_viewport.x = 0; m_viewport.y = 0; m_viewport.w = w; m_viewport.h = h; m_viewport.minDepth = 0; m_viewport.maxDepth = 1.0f; #if !APIABSTRACTION_IOS #if APIABSTRACTION_PS3 assert(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) == GL_FRAMEBUFFER_COMPLETE_OES); #else assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); #endif #endif #if APIABSTRACTION_PS3 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); // back to default #else glBindFramebuffer(GL_FRAMEBUFFER, 0); // back to default #endif #elif APIABSTRACTION_D3D11 m_viewport.TopLeftX = 0; m_viewport.TopLeftY = 0; m_viewport.Width = w; m_viewport.Height = h; m_viewport.MinDepth = 0.0f; m_viewport.MaxDepth = 1.0f; D3D11Renderer *pD3D11Renderer = static_cast<D3D11Renderer *>(m_pContext->getGPUScreen()); ID3D11Device *pDevice = pD3D11Renderer->m_pD3DDevice; ID3D11DeviceContext *pDeviceContext = pD3D11Renderer->m_pD3DContext; //ID3D11Texture2D *pColorMap = 0; D3D11_TEXTURE2D_DESC texDesc; texDesc.Width = w; texDesc.Height = h; texDesc.MipLevels = 0; texDesc.ArraySize = 1; texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texDesc.SampleDesc.Count = 1; texDesc.SampleDesc.Quality = 0; texDesc.Usage = D3D11_USAGE_DEFAULT; texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; texDesc.CPUAccessFlags = 0; texDesc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS; HRESULT hr = pDevice->CreateTexture2D(&texDesc, 0, &m_pTexture); assert(SUCCEEDED(hr)); // Null description means to create a view to all mipmap levels // using the format the texture was created with hr = pDevice->CreateRenderTargetView(m_pTexture, 0, &m_pRenderTargetView); assert(SUCCEEDED(hr)); hr = pDevice->CreateShaderResourceView(m_pTexture, 0, &m_pShaderResourceView); assert(SUCCEEDED(hr)); #endif }
void FrameBuffer::Init(const ax::Size& size) { #ifdef ANDROID glGenFramebuffersOES(1, &_frameBuffer); glBindFramebufferOES(GL_FRAMEBUFFER_OES, _frameBuffer); #else glGenFramebuffers(1, &_frameBuffer); glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer); #endif // Create texture. glGenTextures(1, &_frameBufferTexture); glBindTexture(GL_TEXTURE_2D, _frameBufferTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); //-------------------------------------------------------------------------------------------------------------------- // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); #ifdef ANDROID // NULL means reserve texture memory, but texels are undefined. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); // Attach 2D texture to this FBO. glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, _frameBufferTexture, 0); // Does the GPU support current FBO configuration. GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); if (status != GL_FRAMEBUFFER_COMPLETE_OES) { ax::Error("Generating frame buffer : ", status); } #else // NULL means reserve texture memory, but texels are undefined. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); // Attach 2D texture to this FBO. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _frameBufferTexture, 0); // Does the GPU support current FBO configuration. GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE) { ax::Error("Generating frame buffer : ", status); } #endif #ifdef ANDROID glBindFramebufferOES(GL_FRAMEBUFFER_OES, _frameBuffer); glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); #else glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer); glBindFramebuffer(GL_FRAMEBUFFER, 0); #endif GLenum err = GL_NO_ERROR; while((err = glGetError()) != GL_NO_ERROR) { ax::Error("GL :", err); } }
void initTextureWithCGImage(CGImageRef image) { int i; // Query renderer capabilities that affect this app's rendering paths renderer.extension[APPLE_texture_2D_limited_npot] = (0 != strstr((char *)glGetString(GL_EXTENSIONS), "GL_APPLE_texture_2D_limited_npot")); renderer.extension[IMG_texture_format_BGRA8888] = (0 != strstr((char *)glGetString(GL_EXTENSIONS), "GL_IMG_texture_format_BGRA8888")); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &renderer.maxTextureSize); // Constant state for the lifetime of the app-- position and unit0 are always used glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnable(GL_TEXTURE_2D); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Load image into texture loadTextureFromCGImage(image, &Input, &renderer); // Modify quad texcoords to match (possibly padded) image for (i = 0; i < 4; i++) { fullquad[i].s *= Input.s; fullquad[i].t *= Input.t; flipquad[i].s *= Input.s; flipquad[i].t *= Input.t; } // Create 1x1 for default constant texture // To enable a texture unit, a valid texture has to be bound even if the combine modes do not access it GLubyte half[4] = { 0x80, 0x80, 0x80, 0x80 }; glActiveTexture(GL_TEXTURE1); glGenTextures(1, &Half.texID); Half.wide = Half.high = 1; Half.s = Half.t = 1.0; glBindTexture(GL_TEXTURE_2D, Half.texID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, half); glActiveTexture(GL_TEXTURE0); // Remember the FBO being used for the display framebuffer glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, (GLint *)&SystemFBO); // Create scratch textures and FBOs glGenTextures(1, &Degen.texID); Degen.wide = Input.wide; Degen.high = Input.high; Degen.s = Input.s; Degen.t = Input.t; glBindTexture(GL_TEXTURE_2D, Degen.texID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Degen.wide, Degen.high, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glGenFramebuffersOES(1, &DegenFBO); glBindFramebufferOES(GL_FRAMEBUFFER_OES, DegenFBO); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, Degen.texID, 0); rt_assert(GL_FRAMEBUFFER_COMPLETE_OES == glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); glGenTextures(1, &Scratch.texID); Scratch.wide = Input.wide; Scratch.high = Input.high; Scratch.s = Input.s; Scratch.t = Input.t; glBindTexture(GL_TEXTURE_2D, Scratch.texID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Scratch.wide, Scratch.high, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glGenFramebuffersOES(1, &ScratchFBO); glBindFramebufferOES(GL_FRAMEBUFFER_OES, ScratchFBO); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, Scratch.texID, 0); rt_assert(GL_FRAMEBUFFER_COMPLETE_OES == glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); glBindFramebufferOES(GL_FRAMEBUFFER_OES, SystemFBO); glCheckError(); }
void GLESFrameBufferObject::initialise() { // Release depth and stencil, if they were bound mManager->releaseRenderBuffer(mDepth); mManager->releaseRenderBuffer(mStencil); mManager->releaseRenderBuffer(mMultisampleColourBuffer); /// First buffer must be bound if(!mColour[0].buffer) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Attachment 0 must have surface attached", "GLESFrameBufferObject::initialise"); } // If we're doing multisampling, then we need another FBO which contains a // renderbuffer which is set up to multisample, and we'll blit it to the final // FBO afterwards to perform the multisample resolve. In that case, the // mMultisampleFB is bound during rendering and is the one with a depth/stencil /// Store basic stats size_t width = mColour[0].buffer->getWidth(); size_t height = mColour[0].buffer->getHeight(); GLuint format = mColour[0].buffer->getGLFormat(); // Bind simple buffer to add colour attachments glBindFramebufferOES(GL_FRAMEBUFFER_OES, mFB); GL_CHECK_ERROR; /// Bind all attachment points to frame buffer for(size_t x=0; x<OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x) { if(mColour[x].buffer) { if(mColour[x].buffer->getWidth() != width || mColour[x].buffer->getHeight() != height) { StringStream ss; ss << "Attachment " << x << " has incompatible size "; ss << mColour[x].buffer->getWidth() << "x" << mColour[x].buffer->getHeight(); ss << ". It must be of the same as the size of surface 0, "; ss << width << "x" << height; ss << "."; OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLESFrameBufferObject::initialise"); } if(mColour[x].buffer->getGLFormat() != format) { StringStream ss; ss << "Attachment " << x << " has incompatible format."; OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLESFrameBufferObject::initialise"); } mColour[x].buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0_OES+x, mColour[x].zoffset); } else { // Detach glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES+x, GL_RENDERBUFFER_OES, 0); GL_CHECK_ERROR; } } // Now deal with depth / stencil if (mMultisampleFB) { // Bind multisample buffer glBindFramebufferOES(GL_FRAMEBUFFER_OES, mMultisampleFB); GL_CHECK_ERROR; // Create AA render buffer (colour) // note, this can be shared too because we blit it to the final FBO // right after the render is finished mMultisampleColourBuffer = mManager->requestRenderBuffer(format, width, height, mNumSamples); // Attach it, because we won't be attaching below and non-multisample has // actually been attached to other FBO mMultisampleColourBuffer.buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0_OES, mMultisampleColourBuffer.zoffset); // depth & stencil will be dealt with below } /// Depth buffer is not handled here anymore. /// See GLESFrameBufferObject::attachDepthBuffer() & RenderSystem::setDepthBufferFor() /// Do glDrawBuffer calls GLenum bufs[OGRE_MAX_MULTIPLE_RENDER_TARGETS]; for(size_t x=0; x<OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x) { // Fill attached colour buffers if(mColour[x].buffer) { bufs[x] = GL_COLOR_ATTACHMENT0_OES + x; } else { bufs[x] = GL_NONE; } } /// Check status GLuint status; status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); GL_CHECK_ERROR; /// Bind main buffer #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS // The screen buffer is 1 on iOS glBindFramebufferOES(GL_FRAMEBUFFER_OES, 1); #else glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); #endif GL_CHECK_ERROR; switch(status) { case GL_FRAMEBUFFER_COMPLETE_OES: // All is good break; case GL_FRAMEBUFFER_UNSUPPORTED_OES: OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "All framebuffer formats with this texture internal format unsupported", "GLESFrameBufferObject::initialise"); default: OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Framebuffer incomplete or other FBO status error", "GLESFrameBufferObject::initialise"); } }
int main(void) { EGLint major, minor, eglCfgCount, eglCfgVisualId, width, height; const IMG_gralloc_module_public_t *module; buffer_handle_t srcBuffer, destBuffer; EGLImageKHR eglSrcImage, eglDestImage; EGLConfig eglConfig, eglFBConfig; GLuint fboName, textureNames[2]; EGLNativeWindowType eglWindow; EGLSurface eglWindowSurface; alloc_device_t *device; EGLContext eglContext; EGLDisplay eglDisplay; int err = 1, stride; GLenum glError; ANativeWindowBuffer sSrcBuffer = { .common.magic = ANDROID_NATIVE_BUFFER_MAGIC, .common.version = sizeof(ANativeWindowBuffer), .common.incRef = incRefNop, .common.decRef = decRefNop, .width = SRC_WIDTH, .height = SRC_HEIGHT, .stride = SRC_STRIDE, .usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, }; ANativeWindowBuffer sDestBuffer = { .common.magic = ANDROID_NATIVE_BUFFER_MAGIC, .common.version = sizeof(ANativeWindowBuffer), .common.incRef = incRefNop, .common.decRef = decRefNop, .width = DEST_WIDTH, .height = DEST_HEIGHT, .stride = DEST_STRIDE, .format = DEST_FORMAT, .usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, }; EGLint eglCfgAttribs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, EGL_ALPHA_SIZE, 0, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, #ifdef EGL_ANDROID_recordable EGL_RECORDABLE_ANDROID, EGL_TRUE, #endif EGL_NONE, }; const float srcVertexArray[2 * 4] = { 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, }; const float texCoordArray[2 * 4] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, }; const float destVertexArray[2 * 4] = { -1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, -1.0f, }; eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); if(eglDisplay == EGL_NO_DISPLAY) { printf("eglGetDisplay failed\n"); goto err_out; } if(!eglInitialize(eglDisplay, &major, &minor)) { printf("eglInitialize failed (err=0x%x)\n", eglGetError()); goto err_out; } if(!eglChooseConfig(eglDisplay, eglCfgAttribs, &eglConfig, 1, &eglCfgCount)) { printf("eglChooseConfig failed (err=0x%x)\n", eglGetError()); goto err_terminate; } if(!eglCfgCount) { printf("eglChooseConfig found no suitable configs\n"); goto err_terminate; } if(!eglGetConfigAttrib(eglDisplay, eglConfig, EGL_NATIVE_VISUAL_ID, &eglCfgVisualId)) { printf("eglGetConfigAttrib failed (err=0x%x)\n", eglGetError()); goto err_terminate; } sSrcBuffer.format = eglCfgVisualId; /* Handle FB rendering ***************************************************/ eglWindow = android_createDisplaySurface(); if(!eglWindow) { printf("android_createDisplaySurface returned NULL\n"); goto err_terminate; } eglWindow->common.incRef(&eglWindow->common); eglFBConfig = findMatchingWindowConfig(eglDisplay, EGL_OPENGL_ES_BIT, eglWindow); /* FIXME: findMatchingWindowConfig returns no error code */ eglContext = eglCreateContext(eglDisplay, eglFBConfig, EGL_NO_CONTEXT, NULL); if(eglContext == EGL_NO_CONTEXT) { printf("eglCreateContext failed (err=0x%x)\n", eglGetError()); goto err_window_decref; } eglWindowSurface = eglCreateWindowSurface(eglDisplay, eglFBConfig, eglWindow, NULL); if(eglWindowSurface == EGL_NO_SURFACE) { printf("eglCreateWindowSurface failed (err=0x%x)\n", eglGetError()); goto err_destroy_context; } if(!eglQuerySurface(eglDisplay, eglWindowSurface, EGL_WIDTH, &width)) { printf("eglQuerySurface #1 failed (err=0x%x)\n", eglGetError()); goto err_destroy_context; } if(!eglQuerySurface(eglDisplay, eglWindowSurface, EGL_HEIGHT, &height)) { printf("eglQuerySurface #2 failed (err=0x%x)\n", eglGetError()); goto err_destroy_context; } if(!eglMakeCurrent(eglDisplay, eglWindowSurface, eglWindowSurface, eglContext)) { printf("eglMakeCurrent failed (err=0x%x)\n", eglGetError()); goto err_destroy_surface; } /* Allocate some compatible buffers with gralloc *************************/ err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&module); if(err) { printf("hw_get_module failed (err=%d)\n", err); goto err_make_non_current; } err = module->base.common.methods->open((const hw_module_t *)module, GRALLOC_HARDWARE_GPU0, (hw_device_t **)&device); if(err) { printf("module->common.methods->open() failed (err=%d)\n", err); goto err_make_non_current; } err = device->alloc(device, SRC_WIDTH, SRC_HEIGHT, eglCfgVisualId, GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, &srcBuffer, &stride); if(err) { printf("device->alloc() failed (err=%d)\n", err); goto err_close; } err = device->alloc(device, DEST_WIDTH, DEST_HEIGHT, DEST_FORMAT, GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, &destBuffer, &stride); if(err) { printf("device->alloc() failed (err=%d)\n", err); goto err_free_src; } err = module->base.registerBuffer(&module->base, srcBuffer); if(err) { printf("module->registerBuffer() failed (err=%d)\n", err); goto err_free_dest; } err = module->base.registerBuffer(&module->base, destBuffer); if(err) { printf("module->registerBuffer() failed (err=%d)\n", err); goto err_unregister_src; } sSrcBuffer.handle = srcBuffer; sDestBuffer.handle = destBuffer; /* Make some EGLImageKHRs out of them ************************************/ eglSrcImage = eglCreateImageKHR(eglDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)&sSrcBuffer, 0); if(eglSrcImage == EGL_NO_IMAGE_KHR) { printf("eglCreateImageKHR #1 failed (err=0x%x)\n", eglGetError()); goto err_unregister_dest; } eglDestImage = eglCreateImageKHR(eglDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)&sDestBuffer, 0); if(eglDestImage == EGL_NO_IMAGE_KHR) { printf("eglCreateImageKHR #2 failed (err=0x%x)\n", eglGetError()); goto err_destroy_src_image; } /* Create funny textures *************************************************/ glGenTextures(2, textureNames); glError = glGetError(); if(glError != GL_NO_ERROR) { printf("glGenTextures generated error 0x%x\n", glError); goto err_destroy_dest_image; } glBindTexture(GL_TEXTURE_2D, textureNames[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglSrcImage); glError = glGetError(); if(glError != GL_NO_ERROR) { printf("glEGLImageTargetTexture2DOES generated error 0x%x\n", glError); goto err_delete_textures; } glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureNames[1]); glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, eglDestImage); glError = glGetError(); if(glError != GL_NO_ERROR) { printf("glEGLImageTargetTexture2DOES generated error 0x%x\n", glError); goto err_delete_textures; } /* Create FBO ************************************************************/ glGenFramebuffersOES(1, &fboName); glError = glGetError(); if(glError != GL_NO_ERROR) { printf("glGenFrameBuffersOES generated error 0x%x\n", glError); goto err_delete_textures; } glBindFramebufferOES(GL_FRAMEBUFFER_OES, fboName); glError = glGetError(); if(glError != GL_NO_ERROR) { printf("glBindFramebufferOES generated error 0x%x\n", glError); goto err_delete_framebuffer; } glBindTexture(GL_TEXTURE_2D, textureNames[0]); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, textureNames[0], 0); glError = glGetError(); if(glError != GL_NO_ERROR) { printf("glFramebufferTexture2DOES generated error 0x%x\n", glError); goto err_delete_framebuffer; } /*************************************************************************/ glError = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); if(glError != GL_FRAMEBUFFER_COMPLETE_OES) { printf("glCheckFramebufferStatus generated error 0x%x\n", glError); goto err_delete_framebuffer; } /* Draw some stuff */ { const float vertexArray[2 * 4] = { -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, }; const float colorArray[4 * 4] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, }; char dummy[4]; glViewport(0, 0, SRC_WIDTH, SRC_HEIGHT); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertexArray); glColorPointer(4, GL_FLOAT, 0, colorArray); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, dummy); } /* RGB -> YUV blit */ err = module->Blit2(module, srcBuffer, destBuffer, SRC_WIDTH, SRC_HEIGHT, 0, 0); if(err) { printf("module->Blit2() failed (err=%d)\n", err); goto err_delete_framebuffer; } /* Present both to screen (should appear identical) */ glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); glViewport(0, 0, width, height); glClearColor(0.0f, 1.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray); glEnable(GL_TEXTURE_EXTERNAL_OES); glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureNames[1]); glVertexPointer(2, GL_FLOAT, 0, destVertexArray); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisable(GL_TEXTURE_EXTERNAL_OES); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, textureNames[0]); glVertexPointer(2, GL_FLOAT, 0, srcVertexArray); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); eglSwapBuffers(eglDisplay, eglWindowSurface); sleep(1); err_delete_framebuffer: glDeleteFramebuffersOES(1, &fboName); err_delete_textures: glDeleteTextures(2, textureNames); err_destroy_dest_image: eglDestroyImageKHR(eglDisplay, eglDestImage); err_destroy_src_image: eglDestroyImageKHR(eglDisplay, eglSrcImage); err_unregister_dest: err = module->base.unregisterBuffer(&module->base, destBuffer); if(err) printf("module->unregisterBuffer() failed (err=%d)\n", err); err_unregister_src: err = module->base.unregisterBuffer(&module->base, srcBuffer); if(err) printf("module->unregisterBuffer() failed (err=%d)\n", err); err_free_dest: err = device->free(device, destBuffer); if(err) printf("device->free() failed (err=%d)\n", err); err_free_src: err = device->free(device, srcBuffer); if(err) printf("device->free() failed (err=%d)\n", err); err_close: err = device->common.close((hw_device_t *)device); if(err) printf("hal->close() failed (err=%d)\n", err); err_make_non_current: eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); err_destroy_surface: eglDestroySurface(eglDisplay, eglWindowSurface); err_destroy_context: eglDestroyContext(eglDisplay, eglContext); err_window_decref: eglWindow->common.decRef(&eglWindow->common); err_terminate: eglTerminate(eglDisplay); err_out: return err; }