예제 #1
0
파일: r_backend.c 프로젝트: DenMSC/qfusion
/*
* RB_BindFrameBufferObject
*/
void RB_BindFrameBufferObject( int object )
{
    int width, height;

    RFB_BindObject( object );

    RFB_CheckObjectStatus();

    RFB_GetObjectSize( object, &width, &height );

    if( rb.gl.fbHeight != height )
        rb.gl.scissorChanged = true;

    rb.gl.fbWidth = width;
    rb.gl.fbHeight = height;
}
예제 #2
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;
}
예제 #3
0
/*
* RFB_AttachTextureToObject
*/
bool RFB_AttachTextureToObject( int object, bool depth, int target, image_t *texture ) {
	r_fbo_t *fbo;
	int attachment;
	GLuint texnum = 0;

	assert( object > 0 && object <= r_num_framebuffer_objects );
	if( object <= 0 || object > r_num_framebuffer_objects ) {
		return false;
	}

	if( target < 0 || target >= MAX_FRAMEBUFFER_COLOR_ATTACHMENTS ) {
		return false;
	}
	if( target > 0 && !glConfig.ext.draw_buffers ) {
		return false;
	}

	fbo = r_framebuffer_objects + object - 1;
	qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo->objectID );

bind:
	if( depth ) {
		attachment = GL_DEPTH_ATTACHMENT_EXT;

		if( texture ) {
			assert( texture->flags & IT_DEPTH );
			texnum = texture->texnum;
			texture->fbo = object;
		}
	} else {
#ifndef GL_ES_VERSION_2_0
		const GLenum fboBuffers[8] = {
			GL_COLOR_ATTACHMENT0_EXT,
			GL_COLOR_ATTACHMENT1_EXT,
			GL_COLOR_ATTACHMENT2_EXT,
			GL_COLOR_ATTACHMENT3_EXT,
			GL_COLOR_ATTACHMENT4_EXT,
			GL_COLOR_ATTACHMENT5_EXT,
			GL_COLOR_ATTACHMENT6_EXT,
			GL_COLOR_ATTACHMENT7_EXT,
		};
#endif

		attachment = GL_COLOR_ATTACHMENT0_EXT + target;

#ifndef GL_ES_VERSION_2_0
		if( target > 0 && texture ) {
			qglDrawBuffersARB( target + 1, fboBuffers );
		} else {
			if( glConfig.ext.draw_buffers ) {
				qglDrawBuffersARB( 0, fboBuffers );
			}
			qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT );
			qglReadBuffer( GL_COLOR_ATTACHMENT0_EXT );
		}
#endif

		if( texture ) {
			assert( !( texture->flags & IT_DEPTH ) );
			texnum = texture->texnum;
			texture->fbo = object;
		}
	}

	// attach texture
	qglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, texnum, 0 );
	if( texture ) {
		if( ( texture->flags & ( IT_DEPTH | IT_STENCIL ) ) == ( IT_DEPTH | IT_STENCIL ) ) {
			qglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texnum, 0 );
		}
	}
	else {
		if( depth ) {
			qglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texnum, 0 );
		}
	}
	qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, r_bound_framebuffer_objectID ? r_bound_framebuffer_object->objectID : 0 );

	// check framebuffer status and unbind if failed
	if( !RFB_CheckObjectStatus() ) {
		if( texture ) {
			texture = NULL;
			goto bind;
		}
		return false;
	}

	if( depth ) {
		fbo->depthTexture = texture;
	} else {
		fbo->colorTexture[target] = texture;
	}
	return true;
}