Example #1
0
/*
* R_BlitTextureToScrFbo
*/
static void R_BlitTextureToScrFbo( const refdef_t *fd, image_t *image, int dstFbo, 
	int program_type, const vec4_t color, int blendMask )
{
	int x, y;
	int w, h;

	RB_BindFrameBufferObject( dstFbo );

	if( !dstFbo ) {
		// default framebuffer
		// set the viewport to full resolution
		// but keep the scissoring region
		x = fd->x;
		y = fd->y;
		w = fd->width;
		h = fd->height;
		RB_Viewport( 0, 0, glConfig.width, glConfig.height );
		RB_Scissor( rn.scissor[0], rn.scissor[1], rn.scissor[2], rn.scissor[3] );
	}
	else {
		// aux framebuffer
		// set the viewport to full resolution of the framebuffer
		// set scissor to default framebuffer resolution
		x = 0;
		y = 0;
		w = rf.frameBufferWidth;
		h = rf.frameBufferHeight;
		RB_Viewport( 0, 0, w, h );
		RB_Scissor( 0, 0, glConfig.width, glConfig.height );
	}

	// blit + flip
	R_DrawStretchQuick( x, y, 
		w, h, 
		(float)(x)/image->upload_width, 1.0 - (float)(y)/image->upload_height, 
		(float)(x+w)/image->upload_width, 1.0 - (float)(y+h)/image->upload_height,
		color, program_type, image, blendMask );

	// restore 2D viewport and scissor
	RB_Viewport( 0, 0, rf.frameBufferWidth, rf.frameBufferHeight );
	RB_Scissor( 0, 0, rf.frameBufferWidth, rf.frameBufferHeight );
}
Example #2
0
/*
* R_BlitTextureToScrFbo
*/
static void R_BlitTextureToScrFbo( const refdef_t *fd, image_t *image, int dstFbo, 
	int program_type, const vec4_t color, int blendMask, int numShaderImages, image_t **shaderImages )
{
	int x, y;
	int w, h, fw, fh;
	static char s_name[] = "$builtinpostprocessing";
	static shaderpass_t p;
	static shader_t s;
	int i;
	static tcmod_t tcmod;
	mat4_t m;

	assert( rsh.postProcessingVBO );

	// blit + flip using a static mesh to avoid redundant buffer uploads
	// (also using custom PP effects like FXAA with the stream VBO causes
	// Adreno to mark the VBO as "slow" (due to some weird bug)
	// for the rest of the frame and drop FPS to 10-20).
	RB_FlushDynamicMeshes();

	RB_BindFrameBufferObject( dstFbo );

	if( !dstFbo ) {
		// default framebuffer
		// set the viewport to full resolution
		// but keep the scissoring region
		x = fd->x;
		y = fd->y;
		w = fw = fd->width;
		h = fh = fd->height;
		RB_Viewport( 0, 0, glConfig.width, glConfig.height );
		RB_Scissor( rn.scissor[0], rn.scissor[1], rn.scissor[2], rn.scissor[3] );
	}
	else {
		// aux framebuffer
		// set the viewport to full resolution of the framebuffer (without the NPOT padding if there's one)
		// draw quad on the whole framebuffer texture
		// set scissor to default framebuffer resolution
		image_t *cb = RFB_GetObjectTextureAttachment( dstFbo, false );
		x = 0;
		y = 0;
		w = fw = rf.frameBufferWidth;
		h = fh = rf.frameBufferHeight;
		if( cb ) {
			fw = cb->upload_width;
			fh = cb->upload_height;
		}
		RB_Viewport( 0, 0, w, h );
		RB_Scissor( 0, 0, glConfig.width, glConfig.height );
	}

	s.vattribs = VATTRIB_POSITION_BIT|VATTRIB_TEXCOORDS_BIT;
	s.sort = SHADER_SORT_NEAREST;
	s.numpasses = 1;
	s.name = s_name;
	s.passes = &p;

	p.rgbgen.type = RGB_GEN_IDENTITY;
	p.alphagen.type = ALPHA_GEN_IDENTITY;
	p.tcgen = TC_GEN_NONE;
	p.images[0] = image;
	for( i = 0; i < numShaderImages; i++ )
		p.images[i + 1] = shaderImages[i];
	p.flags = blendMask;
	p.program_type = program_type;

	if( !dstFbo ) {
		tcmod.type = TC_MOD_TRANSFORM;
		tcmod.args[0] = ( float )( w ) / ( float )( image->upload_width );
		tcmod.args[1] = ( float )( h ) / ( float )( image->upload_height );
		tcmod.args[4] = ( float )( x ) / ( float )( image->upload_width );
		tcmod.args[5] = ( float )( image->upload_height - h - y ) / ( float )( image->upload_height );
		p.numtcmods = 1;
		p.tcmods = &tcmod;
	}
	else {
		p.numtcmods = 0;
	}

	Matrix4_Identity( m );
	Matrix4_Scale2D( m, fw, fh );
	Matrix4_Translate2D( m, x, y );
	RB_LoadObjectMatrix( m );

	RB_BindShader( NULL, &s, NULL );
	RB_BindVBO( rsh.postProcessingVBO->index, GL_TRIANGLES );
	RB_DrawElements( 0, 4, 0, 6, 0, 0, 0, 0 );

	RB_LoadObjectMatrix( mat4x4_identity );

	// restore 2D viewport and scissor
	RB_Viewport( 0, 0, rf.frameBufferWidth, rf.frameBufferHeight );
	RB_Scissor( 0, 0, rf.frameBufferWidth, rf.frameBufferHeight );
}
Example #3
0
/*
* R_ResampleCinematicFrame
*/
static image_t *R_ResampleCinematicFrame( r_cinhandle_t *handle )
{
	const int samples = 4;

	if( !handle->pic ) {
		// we haven't yet read a new frame, return whatever image we got
		// this will return NULL until at least one frame has been read
		return handle->image;
	}

	if( handle->yuv ) {
		int i;

		if( !handle->yuv_images[0] ) {
			qbyte *fake_data[1] = { NULL };
			const char *letters[3] = { "y", "u", "v" };

			for( i = 0; i < 3; i++ ) {
				handle->yuv_images[i] = R_LoadImage( va( "%s_%s", handle->name, letters[i] ), 
					fake_data, 1, 1, IT_CINEMATIC|IT_LUMINANCE, 1 );
			}
			handle->new_frame = qtrue;
		}
		
		if( handle->new_frame ) {
			int fbo;
			qboolean in2D;
			
			// render/convert three 8-bit YUV images into RGB framebuffer

			in2D = rf.in2D;
			fbo = RFB_BoundObject();

			if( !in2D ) {
				R_PushRefInst();
			}

			R_InitViewportTexture( &handle->image, handle->name, 0, 
				handle->cyuv->image_width, handle->cyuv->image_height, 
				0, IT_CINEMATIC|IT_FRAMEBUFFER, samples );

			R_BindFrameBufferObject( handle->image->fbo );

			R_Set2DMode( qtrue );

			RB_Scissor( 0, 0, handle->image->upload_width, handle->image->upload_height );

			RB_Viewport( 0, 0, handle->image->upload_width, handle->image->upload_height );

			// flip the image vertically because we're rendering to a FBO
			R_DrawStretchRawYUVBuiltin( 
				0, 0, 
				handle->image->upload_width, handle->image->upload_height,
				(float)handle->cyuv->x_offset / handle->cyuv->image_width, 
				(float)handle->cyuv->y_offset / handle->cyuv->image_height, 
				(float)(handle->cyuv->x_offset + handle->cyuv->width) / handle->cyuv->image_width, 
				(float)(handle->cyuv->y_offset + handle->cyuv->height) / handle->cyuv->image_height, 
				handle->cyuv->yuv, handle->yuv_images, 2 );

			if( !in2D ) {
				R_PopRefInst( 0 );
			}
			R_BindFrameBufferObject( fbo );

			R_Set2DMode( in2D );

			handle->new_frame = qfalse;
		}
	}
	else {
		if( !handle->image ) {
			handle->image = R_LoadImage( handle->name, &handle->pic, handle->width, handle->height, 
				IT_CINEMATIC, samples );
			handle->new_frame = qfalse;
		} else if( handle->new_frame ) {
			R_ReplaceImage( handle->image, &handle->pic, handle->width, handle->height, 
				handle->image->flags, samples );
			handle->new_frame = qfalse;
		}
	}

	return handle->image;
}
Example #4
0
/*
* R_UploadCinematicFrame
*/
static void R_UploadCinematicFrame( r_cinhandle_t *handle ) {
	const int samples = 4;

	ri.Mutex_Lock( handle->lock );

	if( !handle->cin || !handle->pic ) {
		ri.Mutex_Unlock( handle->lock );
		return;
	}

	if( handle->yuv ) {
		int i;

		if( !handle->yuv_images[0] ) {
			char tn[256];
			uint8_t *fake_data[1] = { NULL };
			const char *letters[3] = { "y", "u", "v" };

			for( i = 0; i < 3; i++ ) {
				handle->yuv_images[i] = R_LoadImage(
					va_r( tn, sizeof( tn ), "%s_%s", handle->name, letters[i] ),
					fake_data, 1, 1, IT_SPECIAL | IT_NO_DATA_SYNC, 1, IMAGE_TAG_GENERIC, 1 );
			}
			handle->new_frame = true;
		}

		if( handle->new_frame ) {
			bool multiSamples2D;
			bool in2D;

			// render/convert three 8-bit YUV images into RGB framebuffer
			in2D = rf.twoD.enabled;
			multiSamples2D = rf.twoD.multiSamples;

			if( in2D ) {
				R_End2D();
			} else {
				R_PushRefInst();
			}

			R_InitViewportTexture( &handle->image, handle->name, 0,
								   handle->cyuv->image_width, handle->cyuv->image_height,
								   0, IT_SPECIAL | IT_FRAMEBUFFER, IMAGE_TAG_GENERIC, samples );

			R_BindFrameBufferObject( handle->image->fbo );

			R_SetupGL2D();

			RB_Scissor( 0, 0, handle->image->upload_width, handle->image->upload_height );

			RB_Viewport( 0, 0, handle->image->upload_width, handle->image->upload_height );

			R_UploadRawYUVPic( handle->yuv_images, handle->cyuv->yuv );

			// flip the image vertically because we're rendering to a FBO
			R_DrawStretchRawYUVBuiltin(
				0, 0,
				handle->image->upload_width, handle->image->upload_height,
				(float)handle->cyuv->x_offset / handle->cyuv->image_width,
				(float)handle->cyuv->y_offset / handle->cyuv->image_height,
				(float)( handle->cyuv->x_offset + handle->cyuv->width ) / handle->cyuv->image_width,
				(float)( handle->cyuv->y_offset + handle->cyuv->height ) / handle->cyuv->image_height,
				handle->yuv_images, 2 );

			if( in2D ) {
				R_Begin2D( multiSamples2D );
			} else {
				R_PopRefInst();
			}

			handle->new_frame = false;
		}
	} else {
		if( !handle->image ) {
			handle->image = R_LoadImage( handle->name, (uint8_t **)&handle->pic, handle->width, handle->height,
										 IT_SPECIAL | IT_NO_DATA_SYNC, 1, IMAGE_TAG_GENERIC, samples );
		}

		if( handle->new_frame ) {
			R_ReplaceImage( handle->image, (uint8_t **)&handle->pic, handle->width, handle->height,
							handle->image->flags, 1, samples );
			handle->new_frame = false;
		}
	}

	ri.Mutex_Unlock( handle->lock );
}