Esempio n. 1
0
GLvoid APIENTRY GLDSA_NamedRenderbufferStorageMultisample(GLuint renderbuffer,
	GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
{
	GL_BindRenderbuffer(renderbuffer);
	qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, internalformat, width, height);
}
Esempio n. 2
0
/**
 * @brief create a new framebuffer object
 * @param[in] width The width of the framebuffer
 * @param[in] height The height of the framebuffer
 * @param[in] ntextures The amount of textures for this framebuffer. See also the filters array.
 * @param[in] depth Also generate a depth buffer
 * @param[in] halfFloat Use half float pixel format
 * @param[in] filters Filters for the textures. Must have @c ntextures entries
 */
r_framebuffer_t * R_CreateFramebuffer (int width, int height, int ntextures, bool depth, bool halfFloat, unsigned int *filters)
{
	r_framebuffer_t *buf;
	int i;

	if (!r_state.frameBufferObjectsInitialized) {
		Com_Printf("Warning: framebuffer creation failed; framebuffers not initialized!\n");
		return NULL;
	}

	if (frameBufferObjectCount >= lengthof(frameBufferObjects)) {
		Com_Printf("Warning: framebuffer creation failed; already created too many framebuffers!\n");
		return NULL;
	}

	buf = &frameBufferObjects[frameBufferObjectCount++];
	OBJZERO(*buf);

	if (ntextures > r_config.maxDrawBuffers) {
		Com_Printf("Couldn't allocate requested number of drawBuffers in R_SetupFramebuffer!\n");
		ntextures = r_config.maxDrawBuffers;
	}

	Vector4Clear(buf->clearColor);

	buf->width = width;
	buf->height = height;
	R_SetupViewport(buf, 0, 0, width, height);

	buf->nTextures = ntextures;
	buf->textures = Mem_AllocTypeN(unsigned int, ntextures);

	buf->pixelFormat = halfFloat ? GL_RGBA16F_ARB : GL_RGBA8;
	buf->byteFormat = halfFloat ? GL_HALF_FLOAT_ARB : GL_UNSIGNED_BYTE;

	/* Presence of depth buffer indicates render target that could use antialiasing*/
	if (depth) {
		/** @todo also check if we are running on older (SM2.0) hardware, which doesn't support antialiased MRT */
		if (qglRenderbufferStorageMultisampleEXT && qglBlitFramebuffer) {
			int samples = std::min(4, std::max(0, r_multisample->integer));
			if (samples>1)
				buf->samples = samples;
		}
	}

	for (i = 0; i < buf->nTextures; i++) {
		buf->textures[i] = R_GetFreeFBOTexture();
		glBindTexture(GL_TEXTURE_2D, buf->textures[i]);
		glTexImage2D(GL_TEXTURE_2D, 0, buf->pixelFormat, buf->width, buf->height, 0, GL_RGBA, buf->byteFormat, 0);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filters[i]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		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_GENERATE_MIPMAP, GL_TRUE);
		qglGenerateMipmapEXT(GL_TEXTURE_2D);
		if (r_config.anisotropic)
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_config.maxAnisotropic);

		R_CheckError();
	}
	glBindTexture(GL_TEXTURE_2D, 0);

	/* create FBO itself */
	qglGenFramebuffersEXT(1, &buf->fbo);
	R_CheckError();
	qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, buf->fbo);

	/* create&attach depth renderbuffer */
	if (depth) {
		qglGenRenderbuffersEXT(1, &buf->depth);
		qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, buf->depth);
		if (buf->samples)
			qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, buf->samples, GL_DEPTH_COMPONENT, buf->width, buf->height);
		else
			qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, buf->width, buf->height);
		qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, buf->depth);
	} else {
		buf->depth = 0;
	}

	/* create multisample color buffers if needed */
	if (buf->samples) {
		/* generate color buffers */
		for (i = 0; i < buf->nTextures; i++) {
			unsigned colorbuffer;
			qglGenRenderbuffersEXT(1, &colorbuffer);
			qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, colorbuffer);
			qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, buf->samples, buf->pixelFormat, buf->width, buf->height);
			qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, colorAttachments[i], GL_RENDERBUFFER_EXT, colorbuffer);
			R_CheckError();
		}
		/* proxy framebuffer object for resolving MSAA */
		qglGenFramebuffersEXT(1, &buf->proxyFBO);
		R_CheckError();
		qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, buf->proxyFBO);
	}

	/* Whether multisampling was enabled or not, current FBO should be populated with render-to-texture bindings */
	for (i = 0; i < buf->nTextures; i++) {
		qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, colorAttachments[i], GL_TEXTURE_2D, buf->textures[i], 0);
		R_CheckError();
	}

	R_CheckError();

	/* unbind the framebuffer and return to default state */
	qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

	return buf;
}
Esempio n. 3
0
void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample)
{
	uint32_t *pRenderBuffer;
	GLenum attachment;
	qboolean absent;

	switch(format)
	{
		case GL_RGB:
		case GL_RGBA:
		case GL_RGB8:
		case GL_RGBA8:
		case GL_RGB16F_ARB:
		case GL_RGBA16F_ARB:
		case GL_RGB32F_ARB:
		case GL_RGBA32F_ARB:
			fbo->colorFormat = format;
			pRenderBuffer = &fbo->colorBuffers[index];
			attachment = GL_COLOR_ATTACHMENT0_EXT + index;
			break;

		case GL_DEPTH_COMPONENT:
		case GL_DEPTH_COMPONENT16_ARB:
		case GL_DEPTH_COMPONENT24_ARB:
		case GL_DEPTH_COMPONENT32_ARB:
			fbo->depthFormat = format;
			pRenderBuffer = &fbo->depthBuffer;
			attachment = GL_DEPTH_ATTACHMENT_EXT;
			break;

		case GL_STENCIL_INDEX:
		case GL_STENCIL_INDEX1_EXT:
		case GL_STENCIL_INDEX4_EXT:
		case GL_STENCIL_INDEX8_EXT:
		case GL_STENCIL_INDEX16_EXT:
			fbo->stencilFormat = format;
			pRenderBuffer = &fbo->stencilBuffer;
			attachment = GL_STENCIL_ATTACHMENT_EXT;
			break;

		case GL_DEPTH_STENCIL_EXT:
		case GL_DEPTH24_STENCIL8_EXT:
			fbo->packedDepthStencilFormat = format;
			pRenderBuffer = &fbo->packedDepthStencilBuffer;
			attachment = 0; // special for stencil and depth
			break;

		default:
			ri.Printf(PRINT_WARNING, "FBO_CreateBuffer: invalid format %d\n", format);
			return;
	}

	absent = *pRenderBuffer == 0;
	if (absent)
		qglGenRenderbuffersEXT(1, pRenderBuffer);

	qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, *pRenderBuffer);
	if (multisample && glRefConfig.framebufferMultisample)
	{
		qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, multisample, format, fbo->width, fbo->height);
	}
	else
	{
		qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, fbo->width, fbo->height);
	}

	if(absent)
	{
		if (attachment == 0)
		{
			qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,   GL_RENDERBUFFER_EXT, *pRenderBuffer);
			qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer);
		}
		else
			qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, *pRenderBuffer);
	}
}
Esempio n. 4
0
/*
* RFB_RegisterObject
*/
int RFB_RegisterObject( int width, int height, bool builtin, bool depthRB, bool stencilRB,
						bool colorRB, int samples, bool useFloat, bool sRGB ) {
	int i;
	int format;
	GLuint fbID;
	GLuint rbID = 0;
	r_fbo_t *fbo = NULL;

	if( !r_frambuffer_objects_initialized ) {
		return 0;
	}

#ifdef GL_ES_VERSION_2_0
	if( samples ) {
		return 0;
	}
#else
	if( samples && !glConfig.ext.framebuffer_multisample ) {
		return 0;
	}
#endif

	for( i = 0, fbo = r_framebuffer_objects; i < r_num_framebuffer_objects; i++, fbo++ ) {
		if( !fbo->objectID ) {
			// free slot
			goto found;
		}
	}

	if( i == MAX_FRAMEBUFFER_OBJECTS ) {
		Com_Printf( S_COLOR_YELLOW "RFB_RegisterObject: framebuffer objects limit exceeded\n" );
		return 0;
	}

	clamp_high( samples, glConfig.maxFramebufferSamples );

	i = r_num_framebuffer_objects++;
	fbo = r_framebuffer_objects + i;

found:
	qglGenFramebuffersEXT( 1, &fbID );
	memset( fbo, 0, sizeof( *fbo ) );
	fbo->objectID = fbID;
	if( builtin ) {
		fbo->registrationSequence = -1;
	} else {
		fbo->registrationSequence = rsh.registrationSequence;
	}
	fbo->width = width;
	fbo->height = height;
	fbo->samples = samples;
	fbo->sRGB = sRGB;

	qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo->objectID );

	if( colorRB ) {
		format = glConfig.forceRGBAFramebuffers ? GL_RGBA : GL_RGB;
		if( useFloat ) {
			format = glConfig.forceRGBAFramebuffers ? GL_RGBA16F_ARB : GL_RGB16F_ARB;
		}

		qglGenRenderbuffersEXT( 1, &rbID );
		fbo->colorRenderBuffer = rbID;
		qglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rbID );

#ifndef GL_ES_VERSION_2_0
		if( samples ) {
			qglRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, samples, format, width, height );
		} else
#endif
		qglRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, format, width, height );
	}
#ifndef GL_ES_VERSION_2_0
	else {
		// until a color texture is attached, don't enable drawing to the buffer
		qglDrawBuffer( GL_NONE );
		qglReadBuffer( GL_NONE );
	}
#endif

	if( depthRB ) {
		qglGenRenderbuffersEXT( 1, &rbID );
		fbo->depthRenderBuffer = rbID;
		qglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rbID );

		if( stencilRB ) {
			format = GL_DEPTH24_STENCIL8_EXT;
		} else if( glConfig.ext.depth24 ) {
			format = GL_DEPTH_COMPONENT24;
		} else if( glConfig.ext.depth_nonlinear ) {
			format = GL_DEPTH_COMPONENT16_NONLINEAR_NV;
		} else {
			format = GL_DEPTH_COMPONENT16;
		}

#ifndef GL_ES_VERSION_2_0
		if( samples ) {
			qglRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, samples, format, width, height );
		} else
#endif
		qglRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, format, width, height );

		if( stencilRB ) {
			fbo->stencilRenderBuffer = rbID;
		}
	}

	if( rbID ) {
		qglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
	}

	if( fbo->colorRenderBuffer ) {
		qglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, fbo->colorRenderBuffer );
	}
	if( fbo->depthRenderBuffer ) {
		qglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->depthRenderBuffer );
	}
	if( fbo->stencilRenderBuffer ) {
		qglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->stencilRenderBuffer );
	}

	if( colorRB && depthRB ) {
		if( !RFB_CheckObjectStatus() ) {
			goto fail;
		}
	}

	if( r_bound_framebuffer_objectID ) {
		qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, r_bound_framebuffer_object->objectID );
	} else {
		qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
	}

	return i + 1;

fail:
	RFB_DeleteObject( fbo );
	qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
	return 0;
}