void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
						S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
{
	GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE;

	LLGLDepthTest depth(write_depth, write_depth);

	gGL.flush();
	if (!source.mFBO || !mFBO)
	{
		llwarns << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
		return;
	}

	if (mSampleBuffer)
	{
		mSampleBuffer->copyContents(source, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
	}
	else
	{
		if (mask == GL_DEPTH_BUFFER_BIT && !mStencil && source.mStencil != mStencil)
		{
			stop_glerror();
		
			glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO);
			check_framebuffer_status();
			gGL.getTexUnit(0)->bind(this, true);
			stop_glerror();
			glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
			stop_glerror();
			glBindFramebuffer(GL_FRAMEBUFFER, 0);
			stop_glerror();
		}
		else
		{
			glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
			stop_glerror();
			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
			stop_glerror();
			check_framebuffer_status();
			stop_glerror();
			if(gGLManager.mIsATI && mask & GL_STENCIL_BUFFER_BIT)
			{
				mask &= ~GL_STENCIL_BUFFER_BIT;
				glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_STENCIL_BUFFER_BIT, filter);
			}
			if(mask)
				glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
			stop_glerror();
			glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
			stop_glerror();
			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
			stop_glerror();
			glBindFramebuffer(GL_FRAMEBUFFER, 0);
			stop_glerror();
		}
	}
}
//static
void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
						S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
{
	if (!source.mFBO)
	{
		llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
	}
	{
		GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE;

		LLGLDepthTest depth(write_depth, write_depth);
		
		glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mSampleBuffer ? source.mSampleBuffer->mFBO : source.mFBO);
		stop_glerror();
		glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
		stop_glerror();
		check_framebuffer_status();
		stop_glerror();
		if(gGLManager.mIsATI && mask & GL_STENCIL_BUFFER_BIT)
		{
			mask &= ~GL_STENCIL_BUFFER_BIT;
			glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_STENCIL_BUFFER_BIT, filter);
		}
		if(mask)
			glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
		stop_glerror();
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
		stop_glerror();
	}
}
void LLRenderTarget::bindTarget()
{
	if (mFBO)
	{
		stop_glerror();
		
			glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
			stop_glerror();
			if (gGLManager.mHasDrawBuffers)
			{ //setup multiple render targets
				GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
										GL_COLOR_ATTACHMENT1,
										GL_COLOR_ATTACHMENT2,
										GL_COLOR_ATTACHMENT3};
				glDrawBuffersARB(mTex.size(), drawbuffers);
			}
			
			if (mTex.empty())
			{ //no color buffer to draw to
				glDrawBuffer(GL_NONE);
				glReadBuffer(GL_NONE);
			}

			check_framebuffer_status();

			stop_glerror();
		}

	glViewport(0, 0, mResX, mResY);
	sBoundTarget = this;
}
void initOpenGl()
{
   glewInit();

   glEnable(GL_DEPTH_TEST);

   reload_shader();

   //mesh and texture for pass 1
   mesh_data = LoadMesh(mesh_name);
   texture_id = LoadTexture(texture_name.c_str());

   //mesh for pass 2 (full screen quadrilateral)
   glGenVertexArrays(1, &quad_vao);
   glBindVertexArray(quad_vao);

   float vertices[] = {1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f};

   //create vertex buffers for vertex coords
   glGenBuffers(1, &quad_vbo);
   glBindBuffer(GL_ARRAY_BUFFER, quad_vbo);
   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
   int pos_loc = glGetAttribLocation(shader_program, "pos_attrib");
   if(pos_loc >= 0)
   {
      glEnableVertexAttribArray(pos_loc);
	   glVertexAttribPointer(pos_loc, 3, GL_FLOAT, false, 0, 0);
   }

   //create texture to render pass 1 into
   const int w = glutGet(GLUT_WINDOW_WIDTH);
   const int h = glutGet(GLUT_WINDOW_HEIGHT);
   glGenTextures(1, &fbo_texture);
   glBindTexture(GL_TEXTURE_2D, fbo_texture);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
   glBindTexture(GL_TEXTURE_2D, 0);   

   //Create renderbuffer for depth.
   glGenRenderbuffers(1, &rbo_id);
   glBindRenderbuffer(GL_RENDERBUFFER, rbo_id);
   glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h);

   //Create the framebuffer object
   glGenFramebuffers(1, &fbo_id);
   glBindFramebuffer(GL_FRAMEBUFFER, fbo_id);
   glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_texture, 0);
   glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo_id); // attach depth renderbuffer

   check_framebuffer_status();

   glBindFramebuffer(GL_FRAMEBUFFER, 0);

}
void LLRenderTarget::addColorAttachment(U32 color_fmt)
{
	if (color_fmt == 0)
	{
		return;
	}

	U32 offset = mTex.size();
	if (offset >= 4 ||
		(offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)))
	{
		llerrs << "Too many color attachments!" << llendl;
	}

	U32 tex;
	LLImageGL::generateTextures(1, &tex);
	gGL.getTexUnit(0)->bindManual(mUsage, tex);

	stop_glerror();

	LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

	stop_glerror();

	if (offset == 0)
	{
		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
	}
	else
	{ //don't filter data attachments
		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
	}
	if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
	{
		gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
	}
	else
	{
		// ATI doesn't support mirrored repeat for rectangular textures.
		gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
	}
	if (mFBO)
	{
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset,
			LLTexUnit::getInternalType(mUsage), tex, 0);
			stop_glerror();

		check_framebuffer_status();
		
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
	}

	mTex.push_back(tex);

}
bool
test_framebuffertexture(GLenum textureType)
{
	bool pass = true;
	GLuint fbo, texture;

	float expected[] = { 0, 1, 0 };

	glGenFramebuffers(1, &fbo);
	glBindFramebuffer(GL_FRAMEBUFFER, fbo);

	texture = create_bind_texture(textureType);

	/* Attach the texture to the framebuffer object */
	glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
			     texture, 0);

	if(!piglit_check_gl_error(GL_NO_ERROR) ||
	   !check_framebuffer_status(GL_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE)) {
		glDeleteFramebuffers(1, &fbo);
		glDeleteTextures(1, &texture);
		printf("Texture Type: %s. Error during setup.\n",
		       piglit_get_gl_enum_name(textureType));
		return false;
	}

	piglit_draw_rect(-1, -1, 2, 2);

	/* If the texture is a multisample texture,
	 * convert it to a 2D texture */
	if(textureType == GL_TEXTURE_2D_MULTISAMPLE ||
	   textureType == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) {
		ConvertMultiSample2DToTexture2D(fbo);
	}

	/* Probe for the expected color value */
	if(textureType == GL_TEXTURE_1D ||
	   textureType == GL_TEXTURE_1D_ARRAY) {
		if(!piglit_probe_rect_rgb(0, 0, 6, 1, expected)) {
			pass = false;
		}
	} else {
		if(!piglit_probe_rect_rgb(0, 0, 6, 6, expected)) {
			pass = false;
		}
	}

	/* Clean up */
	glDeleteFramebuffers(1, &fbo);
	glDeleteTextures(1, &texture);

	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;

	return pass;
}
/* Take a framebuffer object, that has a GL_TEXTURE_2D_MULTISAMPLE
 * or a layer of a GL_TEXTURE_2D_MULTISAMPLE_ARRAY attached to
 * color attachment 0. Then blit that framebuffer object to
 * a new fbo that has a GL_TEXTURE_2D attached. Finally
 * attach the new GL_TEXTURE_2D to the original fbo.
 */
void
ConvertMultiSample2DToTexture2D(GLuint fboRead) {
	GLuint fboDraw, texture;

	glGenFramebuffers(1, &fboDraw);
	glGenTextures(1, &texture);

	glBindFramebuffer(GL_READ_FRAMEBUFFER, fboRead);
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboDraw);

	texture = create_bind_texture(GL_TEXTURE_2D);
	glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
			       GL_TEXTURE_2D, texture, 0);

	if(!check_framebuffer_status(GL_DRAW_FRAMEBUFFER,
				     GL_FRAMEBUFFER_COMPLETE) ||
	   !check_framebuffer_status(GL_READ_FRAMEBUFFER,
				     GL_FRAMEBUFFER_COMPLETE)) {

		piglit_report_result(PIGLIT_FAIL);
	}

	glBlitFramebuffer(0, 0, 6, 6, 0, 0, 6, 6,
			  GL_COLOR_BUFFER_BIT, GL_NEAREST);

	if(!piglit_check_gl_error(GL_NO_ERROR)) {
		glDeleteTextures(1, &texture);
		piglit_report_result(PIGLIT_FAIL);
	}

	glBindFramebuffer(GL_FRAMEBUFFER, fboRead);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
			       GL_TEXTURE_2D, texture, 0);

	glDeleteFramebuffers(1, &fboDraw);

	if(!piglit_check_gl_error(GL_NO_ERROR)) {
		glDeleteTextures(1, &texture);
		piglit_report_result(PIGLIT_FAIL);
	}
}
Beispiel #8
0
    void GLFrameBuffer::onBind() {
        GLGraphicDevice& gd = *checked_cast<GLGraphicDevice*>(&Context::Instance().getGraphicFactory().getGraphicDevice());
        
        gd.bindGLFrameBuffer(mFBO);
        if(mFBO != 0) {
            check_framebuffer_status();

            std::vector<GLenum> buffers(mClearViews.size());
            for(size_t i=0; i<mClearViews.size(); ++i) {
                buffers[i] = static_cast<GLenum>(i + GL_COLOR_ATTACHMENT0_EXT);
            }
            CHECK_GL_CALL(glDrawBuffers((GLsizei)buffers.size(), &buffers[0]));

        } else {
            GLenum targets[] = { GL_BACK_LEFT };
            glDrawBuffers(1, &targets[0]);
        }
    }
void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
{
	if (!mFBO || !target.mFBO)
	{
		llerrs << "Cannot share depth buffer between non FBO render targets." << llendl;
	}

	if (target.mDepth)
	{
		llerrs << "Attempting to override existing depth buffer.  Detach existing buffer first." << llendl;
	}

	if (target.mUseDepth)
	{
		llerrs << "Attempting to override existing shared depth buffer. Detach existing buffer first." << llendl;
	}

	if (mDepth)
	{
		stop_glerror();
		glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO);
		stop_glerror();

		if (mStencil)
		{
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth);
			stop_glerror();
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth);			
			stop_glerror();
			target.mStencil = true;
		}
		else
		{
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
			stop_glerror();
		}

		check_framebuffer_status();

		glBindFramebuffer(GL_FRAMEBUFFER, 0);

		target.mUseDepth = true;
	}
}
bool LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
{
	if (color_fmt == 0)
	{
		return true;
	}

	U32 offset = mTex.size();
	if (offset >= 4 ||
		(offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)))
	{
		llerrs << "Too many color attachments!" << llendl;
	}

	U32 tex;
	glGenRenderbuffers(1, &tex);
	glBindRenderbuffer(GL_RENDERBUFFER, tex);
	stop_glerror();
	clear_glerror();
	glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, color_fmt, mResX, mResY);
	if (glGetError() != GL_NO_ERROR)
	{
		llwarns << "Unable to allocate color buffer for multisample render target." << llendl;
		release();
		return false;
	}
	
	sBytesAllocated += mResX*mResY*4;
	
	if (mFBO)
	{
		glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, GL_RENDERBUFFER, tex);
		check_framebuffer_status();
		glBindFramebuffer(GL_FRAMEBUFFER, 0);
	}

	mTex.push_back(tex);
	return true;
}
Beispiel #11
0
bool test_gl_layer(GLint prog, int layers, float *expected)
{
	bool pass = true;
	GLuint fbo, texture;

	glGenFramebuffers(1, &fbo);
	glGenTextures(1, &texture);

	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
	glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
	glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 10,
		     10, 2, 0, GL_RGB, GL_FLOAT, NULL);

	glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
			     texture, 0);

	if(!check_framebuffer_status(GL_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE) ||
	   !piglit_check_gl_error(GL_NO_ERROR)) {
		piglit_report_result(PIGLIT_FAIL);
	}

	glClear(GL_COLOR_BUFFER_BIT);

	glUseProgram(prog);

	piglit_draw_rect(-1, -1, 2, 2);

	pass = probe_texture_layered_rgb(texture, 0, 0, 0,
					 10, 10, 2, expected) && pass;

	glDeleteTextures(1, &texture);
	glDeleteFramebuffers(1, &fbo);

	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
	return pass;
}
Beispiel #12
0
inline void print_current_framebuffer_status(){
	// check FBO status
	GLenum status = check_framebuffer_status(GL_FRAMEBUFFER);
	switch(status)
	{
		case GL_FRAMEBUFFER_COMPLETE:
			//COUT << "complete" << std::std::endl;
			break;

		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
			std::cerr << "FBO: Attachment is NOT complete" << std::endl;
			break;

		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
			std::cerr << "FBO: Missing attachment" << std::endl;
			break;

		case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
			std::cerr << "FBO: Incomplete draw buffer" << std::endl;
			break;

		case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
			std::cerr << "FBO: Incomplete read buffer" << std::endl;
			break;

		#ifdef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
			std::cerr << "FBO: Attached buffers have different dimensions" << std::endl;
			break;
		#endif

		case GL_FRAMEBUFFER_UNSUPPORTED:
			std::cerr << "FBO: Unsupported by implementation" << std::endl;
			break;

		default:
			std::cerr << "FBO: Unknown error: " << status << std::endl;
			break;
	}
}
void LLRenderTarget::clear(U32 mask_in)
{
	U32 mask = GL_COLOR_BUFFER_BIT;
	if (mUseDepth)
	{
		mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
	}
	if (mFBO)
	{
		check_framebuffer_status();
		stop_glerror();
		glClear(mask & mask_in);
		stop_glerror();
	}
	else
	{
		LLGLEnable scissor(GL_SCISSOR_TEST);
		glScissor(0, 0, mResX, mResY);
		stop_glerror();
		glClear(mask & mask_in);
	}
}
void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref)
{
	if (!ref)
	{
		ref = this;
	}

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
	if (gGLManager.mHasDrawBuffers)
	{ //setup multiple render targets
		GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0_EXT,
								GL_COLOR_ATTACHMENT1_EXT,
								GL_COLOR_ATTACHMENT2_EXT,
								GL_COLOR_ATTACHMENT3_EXT};
		glDrawBuffersARB(ref->mTex.size(), drawbuffers);
	}

	check_framebuffer_status();

	glViewport(0, 0, mResX, mResY);

	sBoundTarget = this;
}
//static
void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
						S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
{
	if (!source.mFBO)
	{
		llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
	}
	{
		GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE;

		LLGLDepthTest depth(write_depth, write_depth);
		
		glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
		stop_glerror();
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
		stop_glerror();
		check_framebuffer_status();
		stop_glerror();
		glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
		stop_glerror();
		glBindFramebuffer(GL_FRAMEBUFFER, 0);
		stop_glerror();
	}
}
void LLRenderTarget::addColorAttachment(U32 color_fmt)
{
    if (color_fmt == 0)
    {
        return;
    }

    U32 offset = mTex.size();
    if (offset >= 4 ||
            (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)))
    {
        llerrs << "Too many color attachments!" << llendl;
    }

    U32 tex;
    LLImageGL::generateTextures(1, &tex);
    gGL.getTexUnit(0)->bindManual(mUsage, tex);

    stop_glerror();


#ifdef GL_ARB_texture_multisample
    if (mSamples > 1)
    {
        glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, color_fmt, mResX, mResY, GL_TRUE);
    }
    else
#else
    llassert_always(mSamples <= 1);
#endif
    {
        LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    }

    stop_glerror();

    if (mSamples == 0)
    {
        if (offset == 0)
        {   //use bilinear filtering on single texture render targets that aren't multisampled
            gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
            stop_glerror();
        }
        else
        {   //don't filter data attachments
            gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
            stop_glerror();
        }

        if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
        {
            gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
            stop_glerror();
        }
        else
        {
            // ATI doesn't support mirrored repeat for rectangular textures.
            gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
            stop_glerror();
        }
    }

    if (mFBO)
    {
        stop_glerror();
        glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset,
                               LLTexUnit::getInternalType(mUsage), tex, 0);
        stop_glerror();

        check_framebuffer_status();

        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

    mTex.push_back(tex);

    if (gDebugGL)
    {   //bind and unbind to validate target
        bindTarget();
        flush();
    }

}
void LLRenderTarget::flush(bool fetch_depth)
{
	gGL.flush();
	if (!mFBO)
	{
		gGL.getTexUnit(0)->bind(this);
		glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY);
		stop_glerror();

		if (fetch_depth)
		{
			if (!mDepth)
			{
				allocateDepth();
			}

			gGL.getTexUnit(0)->bind(this,true);
			glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY);
			stop_glerror();
			//glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8, 0, 0, mResX, mResY, 0);
		}

		gGL.getTexUnit(0)->disable();
	}
	else
	{
		stop_glerror();
		glBindFramebuffer(GL_FRAMEBUFFER, 0);
		stop_glerror();

		if (mSampleBuffer)
		{
			LLGLEnable multisample(GL_MULTISAMPLE);
			stop_glerror();
			glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
			stop_glerror();
			check_framebuffer_status();
			glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleBuffer->mFBO);
			check_framebuffer_status();

			stop_glerror();
			if(gGLManager.mIsATI)
			{
				glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
				glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_STENCIL_BUFFER_BIT, GL_NEAREST);
			}
			else
			{
				glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
			}
			stop_glerror();		

			//Following case never currently evalutes true, but it's still good to have.
			if (mTex.size() > 1)
			{
				for (U32 i = 1; i < mTex.size(); ++i)
				{
					glDrawBuffer(GL_COLOR_ATTACHMENT0 + i);
					glReadBuffer(GL_COLOR_ATTACHMENT0 + i);
					stop_glerror();
					glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST);
					stop_glerror();
				}

				/*for (U32 i = 1; i < mTex.size(); ++i)
				{

					glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
										LLTexUnit::getInternalType(mUsage), mTex[i], 0);
					stop_glerror();
					glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mSampleBuffer->mTex[i]);
					stop_glerror();
					glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST);		
					stop_glerror();
				}

				for (U32 i = 0; i < mTex.size(); ++i)
				{
					glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i,
										LLTexUnit::getInternalType(mUsage), mTex[i], 0);
					stop_glerror();
					glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_RENDERBUFFER, mSampleBuffer->mTex[i]);
					stop_glerror();
				}*/
			}
			glBindFramebuffer(GL_FRAMEBUFFER, 0);
		}
	}
}
void
piglit_init(int argc, char **argv)
{
	int j;
	bool pass = true;
	GLuint fbo, texture, program;

	static const float colors[6*3] = {
		0, 0, 1,
		0, 1, 0,
		0, 1, 1,
		1, 0, 0,
		1, 0, 1,
		1, 1, 0
	};

	program = piglit_build_simple_program_multiple_shaders(
					GL_VERTEX_SHADER, vs_source,
					GL_GEOMETRY_SHADER, gs_source,
					GL_FRAGMENT_SHADER, fs_source,
					0);
	glUseProgram(program);

	/* Retrieve index from vs */
	color_uniform = glGetUniformLocation(program, "color");
	layer_uniform = glGetUniformLocation(program, "layer");

	/* Gen textures */
	glGenFramebuffers(1, &fbo);
	glBindFramebuffer(GL_FRAMEBUFFER, fbo);

	texture = create_bind_texture();
	glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
			     texture, 0);

	if(!check_framebuffer_status(GL_FRAMEBUFFER,
				     GL_FRAMEBUFFER_COMPLETE) ||
	   !piglit_check_gl_error(GL_NO_ERROR)) {
		printf("Error with setup\n");
		piglit_report_result(PIGLIT_FAIL);
	}

	/* draw quad on each layer with set color*/
	glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
	for(j = 0; j < 6; j++) {
		if (j == 3) {
			glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
		}
		glUniform1i(layer_uniform, j);
		glUniform3fv(color_uniform, 1, &colors[j*3]);
		/* rect larger than vp */
		piglit_draw_rect(-2, -2, 4, 4);
	}

	pass = probe_texture_layered_rgb(texture,
					 0, 0, 0, 6, 6, 6, colors) && pass;

	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;

	/* Clean up */
	glDeleteTextures(1, &texture);
	glDeleteFramebuffers(1, &fbo);

	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;

	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
}
Beispiel #19
0
inline bool check_current_framebuffer_status(){
	GLenum status = check_framebuffer_status(GL_FRAMEBUFFER);
	return (status == GL_FRAMEBUFFER_COMPLETE);
}
void LLRenderTarget::flush(bool fetch_depth)
{
	gGL.flush();
	if (!mFBO)
	{
		gGL.getTexUnit(0)->bind(this);
		glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY);

		if (fetch_depth)
		{
			if (!mDepth)
			{
				allocateDepth();
			}

			gGL.getTexUnit(0)->bind(this);
			glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0);
		}

		gGL.getTexUnit(0)->disable();
	}
	else
	{
		stop_glerror();

		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

		stop_glerror();
	
		if (mSampleBuffer)
		{
			LLGLEnable multisample(GL_MULTISAMPLE_ARB);
			stop_glerror();
			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
			stop_glerror();
			check_framebuffer_status();
			glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mSampleBuffer->mFBO);
			check_framebuffer_status();
			
			stop_glerror();
			if(gGLManager.mIsATI)
			{
				glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
				glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_STENCIL_BUFFER_BIT, GL_NEAREST);
			}
			else
				glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
			stop_glerror();		

			if (mTex.size() > 1)
			{		
				for (U32 i = 1; i < mTex.size(); ++i)
				{
					glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
										LLTexUnit::getInternalType(mUsage), mTex[i], 0);
					stop_glerror();
					glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]);
					stop_glerror();
					glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST);		
					stop_glerror();
				}

				for (U32 i = 0; i < mTex.size(); ++i)
				{
					glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i,
										LLTexUnit::getInternalType(mUsage), mTex[i], 0);
					stop_glerror();
					glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]);
					stop_glerror();
				}
			}
		}

		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
	}
}
bool LLRenderTarget::addColorAttachment(U32 color_fmt)
{
	if (color_fmt == 0)
	{
		return true;
	}

	U32 offset = mTex.size();
	if (offset >= 4 ||
		(offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)))
	{
		llerrs << "Too many color attachments!" << llendl;
	}

	U32 tex;
	LLImageGL::generateTextures(1, &tex);
	gGL.getTexUnit(0)->bindManual(mUsage, tex);

	stop_glerror();


	{
		clear_glerror();
		LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
		if (glGetError() != GL_NO_ERROR)
		{
			llwarns << "Could not allocate color buffer for render target." << llendl;
			return false;
		}
	}

	sBytesAllocated += mResX*mResY*4;

	stop_glerror();

	
	if (offset == 0)
		{ //use bilinear filtering on single texture render targets that aren't multisampled
		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
			stop_glerror();
	}
	else
	{ //don't filter data attachments
		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
			stop_glerror();
	}
	if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
	{
		gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
			stop_glerror();
	}
	else
	{
		// ATI doesn't support mirrored repeat for rectangular textures.
		gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
			stop_glerror();
	}
		
	if (mFBO)
	{
		stop_glerror();
		glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset,
			LLTexUnit::getInternalType(mUsage), tex, 0);
			stop_glerror();

		check_framebuffer_status();
		
		glBindFramebuffer(GL_FRAMEBUFFER, 0);
	}

	mTex.push_back(tex);

	if (gDebugGL)
	{ //bind and unbind to validate target
		bindTarget();
		flush();
	}

	return true;
}
Beispiel #22
0
bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil,  LLTexUnit::eTextureType usage, bool use_fbo, U32 samples )
{
	release();
	stop_glerror();

	if (!gGLManager.mHasFramebufferMultisample || !gGLManager.mHasFramebufferObject || !(sUseFBO || use_fbo))
		return false;

	if(color_fmt != GL_RGBA)
	{
		llwarns << "Unsupported color format: " << color_fmt << llendl;
		return false;
	}

	//Restrict to valid sample count
	{
		mSamples = samples;
		//mSamples = llmin(mSamples, (U32)4);	//Cap to prevent memory bloat.
		mSamples = llmin(mSamples, (U32) gGLManager.mMaxSamples);
	}

	if (mSamples <= 1)
		return false;
	
	mResX = resx;
	mResY = resy;

	mUsage = usage;
	mUseDepth = depth;
	mStencil = stencil;
	mColorFormat = color_fmt;

	{

		if (depth)
		{
			stop_glerror();
			if(!allocateDepth())
			{
				release();
				return false;
			}
			stop_glerror();
		}
		glGenFramebuffers(1, (GLuint *) &mFBO);
		glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
		stop_glerror();
		clear_glerror();
		if (mDepth)
		{
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth);
			if (mStencil)
			{
				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth);			
			}
			check_framebuffer_status();
		}
		
		stop_glerror();
		glBindFramebuffer(GL_FRAMEBUFFER, 0);
		stop_glerror();
		
		
	}

	return addColorAttachment(color_fmt);
}