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;
    }
Esempio n. 3
0
// 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;
  }
Esempio n. 5
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
    }
}
Esempio n. 10
0
		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, &current_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;
		}
Esempio n. 11
0
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;
}
Esempio n. 12
0
    /** 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);
    }
Esempio n. 13
0
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
}
Esempio n. 16
0
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
}
Esempio n. 18
0
	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);
		}
	}
Esempio n. 19
0
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");
    }

}
Esempio n. 21
0
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;
}