Exemplo n.º 1
0
/*
* R_StartCinematic
*/
unsigned int R_StartCinematic( const char *arg )
{
	char uploadName[128];
	size_t name_size;
	r_cinhandle_t *handle, *hnode, *next;
	struct cinematics_s *cin;
	qboolean yuv;

	// find cinematics with the same name
	hnode = &r_cinematics_headnode;
	for( handle = hnode->prev; handle != hnode; handle = next )
	{
		next = handle->prev;
		assert( handle->cin );

		// reuse
		if( !Q_stricmp( handle->name, arg ) )
			return handle->id;
	}

	// open the file, read header, etc
	cin = ri.CIN_Open( arg, ri.Sys_Milliseconds(), qtrue, &yuv, NULL );

	// take a free cinematic handle if possible
	if( !r_free_cinematics || !cin )
		return 0;

	handle = r_free_cinematics;
	r_free_cinematics = handle->next;

	// copy name
	name_size = strlen( arg ) + 1;
	handle->name = R_Malloc( name_size );
	memcpy( handle->name, arg, name_size );

	// copy upload name
	Q_snprintfz( uploadName, sizeof( uploadName ), "***r_cinematic%i***", handle->id-1 );
	name_size = strlen( uploadName ) + 1;
	handle->uploadName = R_Malloc( name_size );
	memcpy( handle->uploadName, uploadName, name_size );

	handle->cin = cin;
	handle->new_frame = qfalse;
	handle->yuv = yuv;
	handle->image = NULL;
	handle->yuv_images[0] = handle->yuv_images[1] = handle->yuv_images[2] = NULL;
	handle->registrationSequence = rsh.registrationSequence;
	handle->pic = NULL;
	handle->cyuv = NULL;

	// put handle at the start of the list
	handle->prev = &r_cinematics_headnode;
	handle->next = r_cinematics_headnode.next;
	handle->next->prev = handle;
	handle->prev->next = handle;

	return handle->id;
}
Exemplo n.º 2
0
// if return == true, no further action needed by the caller...
//
void *RE_RegisterModels_Malloc(int iSize, void *pvDiskBufferIfJustLoaded, const char *psModelFileName, qboolean *pqbAlreadyFound, memtag_t eTag)
{
	char sModelName[MAX_QPATH];

	Q_strncpyz(sModelName,psModelFileName,sizeof(sModelName));
	Q_strlwr  (sModelName);

	CachedEndianedModelBinary_t &ModelBin = (*CachedModels)[sModelName];

	if (ModelBin.pModelDiskImage == NULL)
	{
		// ... then this entry has only just been created, ie we need to load it fully...
		//
		// new, instead of doing a R_Malloc and assigning that we just morph the disk buffer alloc
		//	then don't thrown it away on return - cuts down on mem overhead
		//
		// ... groan, but not if doing a limb hierarchy creation (some VV stuff?), in which case it's NULL
		//
		if ( pvDiskBufferIfJustLoaded )
		{
			R_MorphMallocTag( pvDiskBufferIfJustLoaded, eTag );
		}
		else
		{
			pvDiskBufferIfJustLoaded =  R_Malloc(iSize,eTag, qfalse );
		}

		ModelBin.pModelDiskImage= pvDiskBufferIfJustLoaded;
		ModelBin.iAllocSize		= iSize;
		*pqbAlreadyFound		= qfalse;
	}
	else
	{
		// if we already had this model entry, then re-register all the shaders it wanted...
		//
		const int iEntries = ModelBin.ShaderRegisterData.size();
		for (int i=0; i<iEntries; i++)
		{
			int iShaderNameOffset	= ModelBin.ShaderRegisterData[i].first;
			int iShaderPokeOffset	= ModelBin.ShaderRegisterData[i].second;

			const char *const psShaderName	 =		   &((char*)ModelBin.pModelDiskImage)[iShaderNameOffset];
				  int  *const piShaderPokePtr= (int *) &((char*)ModelBin.pModelDiskImage)[iShaderPokeOffset];

			shader_t *sh = R_FindShader( psShaderName, lightmapsNone, stylesDefault, qtrue );

			if ( sh->defaultShader )
			{
				*piShaderPokePtr = 0;
			} else {
				*piShaderPokePtr = sh->index;
			}
		}
		*pqbAlreadyFound = qtrue;	// tell caller not to re-Endian or re-Shader this binary
	}

	ModelBin.iLastLevelUsedOn = RE_RegisterMedia_GetLevel();

	return ModelBin.pModelDiskImage;
}
Exemplo n.º 3
0
/*
* R_VBOVertBuffer
*/
static void *R_VBOVertBuffer( unsigned numVerts, size_t vertSize )
{
	size_t size = numVerts * vertSize;
	if( size > r_vbo_tempvsoupsize ) {
		if( r_vbo_tempvsoup )
			R_Free( r_vbo_tempvsoup );
		r_vbo_tempvsoupsize = size;
		r_vbo_tempvsoup = ( float * )R_Malloc( size );
	}
	return r_vbo_tempvsoup;
}
Exemplo n.º 4
0
/*
* R_VBOElemBuffer
*/
static elem_t *R_VBOElemBuffer( unsigned numElems )
{
	if( numElems > r_vbo_numtempelems ) {
		if( r_vbo_numtempelems )
			R_Free( r_vbo_tempelems );
		r_vbo_numtempelems = numElems;
		r_vbo_tempelems = ( elem_t * )R_Malloc( sizeof( *r_vbo_tempelems ) * numElems );
	}

	return r_vbo_tempelems;
}
Exemplo n.º 5
0
void RE_SaveJPG(const char * filename, int quality, int image_width, int image_height, byte *image_buffer, int padding)
{
	byte *out;
	size_t bufSize;

	bufSize = image_width * image_height * 3;
	out = (byte *) R_Malloc( bufSize, TAG_TEMP_WORKSPACE, qfalse );

	bufSize = RE_SaveJPGToBuffer(out, bufSize, quality, image_width, image_height, image_buffer, padding, false);
	ri.FS_WriteFile(filename, out, bufSize);

	R_Free(out);
}
Exemplo n.º 6
0
/*
================
R_MipMap2

Uses temp mem, but then copies back to input, quartering the size of the texture
Proper linear filter
================
*/
static void R_MipMap2( unsigned *in, int inWidth, int inHeight ) {
	int			i, j, k;
	byte		*outpix;
	int			inWidthMask, inHeightMask;
	int			total;
	int			outWidth, outHeight;
	unsigned	*temp;

	outWidth = inWidth >> 1;
	outHeight = inHeight >> 1;
	temp = (unsigned int *) R_Malloc( outWidth * outHeight * 4, TAG_TEMP_WORKSPACE, qfalse );

	inWidthMask = inWidth - 1;
	inHeightMask = inHeight - 1;

	for ( i = 0 ; i < outHeight ; i++ ) {
		for ( j = 0 ; j < outWidth ; j++ ) {
			outpix = (byte *) ( temp + i * outWidth + j );
			for ( k = 0 ; k < 4 ; k++ ) {
				total =
					1 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] +
					2 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] +
					2 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] +
					1 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] +

					2 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] +
					4 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] +
					4 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] +
					2 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] +

					2 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] +
					4 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] +
					4 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] +
					2 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] +

					1 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] +
					2 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] +
					2 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] +
					1 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k];
				outpix[k] = total / 36;
			}
		}
	}

	memcpy( in, temp, outWidth * outHeight * 4 );
	R_Free( temp );
}
Exemplo n.º 7
0
/*
* R_InitCinematics
*/
void R_InitCinematics( void ) {
	int i;

	r_cinematics = R_Malloc( sizeof( r_cinhandle_t ) * MAX_CINEMATICS );
	memset( r_cinematics, 0, sizeof( r_cinhandle_t ) * MAX_CINEMATICS );

	// link cinemtics
	r_free_cinematics = r_cinematics;
	r_cinematics_headnode.id = 0;
	r_cinematics_headnode.prev = &r_cinematics_headnode;
	r_cinematics_headnode.next = &r_cinematics_headnode;
	for( i = 0; i < MAX_CINEMATICS - 1; i++ ) {
		if( i < MAX_CINEMATICS - 1 ) {
			r_cinematics[i].next = &r_cinematics[i + 1];
		}
		r_cinematics[i].id = i + 1;
	}
}
Exemplo n.º 8
0
/*
* R_SkinFileForName
*/
static skinfile_t *R_SkinFileForName( const char *name ) {
	char filename[MAX_QPATH];
	int i;
	char *buffer;
	skinfile_t *skinfile;

	Q_strncpyz( filename, name, sizeof( filename ) );
	COM_DefaultExtension( filename, ".skin", sizeof( filename ) );

	for( i = 0, skinfile = r_skinfiles; i < r_numskinfiles; i++, skinfile++ ) {
		if( !skinfile->name ) {
			break; // free slot
		}
		if( !Q_stricmp( skinfile->name, filename ) ) {
			return skinfile;
		}
	}

	if( i == MAX_SKINFILES ) {
		Com_Printf( S_COLOR_YELLOW "R_SkinFile_Load: Skin files limit exceeded\n" );
		return NULL;
	}

	if( R_LoadFile( filename, (void **)&buffer ) == -1 ) {
		ri.Com_DPrintf( S_COLOR_YELLOW "R_SkinFile_Load: Failed to load %s\n", name );
		return NULL;
	}

	r_numskinfiles++;
	skinfile = &r_skinfiles[i];
	skinfile->name = R_CopyString( filename );

	skinfile->numpairs = SkinFile_ParseBuffer( buffer, NULL );
	if( skinfile->numpairs ) {
		skinfile->pairs = R_Malloc( skinfile->numpairs * sizeof( mesh_shader_pair_t ) );
		SkinFile_ParseBuffer( buffer, skinfile->pairs );
	} else {
		ri.Com_DPrintf( S_COLOR_YELLOW "R_SkinFile_Load: no mesh/shader pairs in %s\n", name );
	}

	R_FreeFile( (void *)buffer );

	return skinfile;
}
Exemplo n.º 9
0
/*
* R_ReserveDrawSurfaces
*/
static void R_ReserveDrawSurfaces( drawList_t *list, int minMeshes )
{
	int oldSize, newSize;
	sortedDrawSurf_t *newDs;
	sortedDrawSurf_t *ds = list->drawSurfs;
	int maxMeshes = list->maxDrawSurfs;

	oldSize = maxMeshes;
	newSize = max( minMeshes, oldSize * 2 );

	newDs = R_Malloc( newSize * sizeof( sortedDrawSurf_t ) );
	if( ds ) {
		memcpy( newDs, ds, oldSize * sizeof( sortedDrawSurf_t ) );
		R_Free( ds );
	}
	
	list->drawSurfs = newDs;
	list->maxDrawSurfs = newSize;
}
Exemplo n.º 10
0
/*
* R_AddDebugBounds
*/
void R_AddDebugBounds( const vec3_t mins, const vec3_t maxs, const byte_vec4_t color )
{
	unsigned i;

	i = r_num_debug_bounds;
	r_num_debug_bounds++;

	if( r_num_debug_bounds > r_debug_bounds_current_size )
	{
		r_debug_bounds_current_size = ALIGN( r_num_debug_bounds, 256 );
		if( r_debug_bounds )
			r_debug_bounds = R_Realloc( r_debug_bounds, r_debug_bounds_current_size * sizeof( r_debug_bound_t ) );
		else
			r_debug_bounds = R_Malloc( r_debug_bounds_current_size * sizeof( r_debug_bound_t ) );
	}

	VectorCopy( mins, r_debug_bounds[i].mins );
	VectorCopy( maxs, r_debug_bounds[i].maxs );
	Vector4Copy( color, r_debug_bounds[i].color );
}
Exemplo n.º 11
0
// I added this function for development purposes (and it's VM-safe) so we don't have problems
//	with our use of cached models but uncached animation.cfg files (so frame sequences are out of sync
//	if someone rebuild the model while you're ingame and you change levels)...
//
// Usage:  call with psDest == NULL for a size enquire (for malloc),
//				then with NZ ptr for it to copy to your supplied buffer...
//
int RE_GetAnimationCFG(const char *psCFGFilename, char *psDest, int iDestSize)
{
	char *psText = NULL;

	AnimationCFGs_t::iterator it = AnimationCFGs.find(psCFGFilename);
	if (it != AnimationCFGs.end())
	{
		psText = (*it).second;
	}
	else
	{
		// not found, so load it...
		//
		fileHandle_t f;
		int iLen = ri.FS_FOpenFileRead( psCFGFilename, &f, qfalse );
		if (iLen <= 0)
		{
			return 0;
		}

		psText = (char *) R_Malloc( iLen+1, TAG_ANIMATION_CFG, qfalse );

		ri.FS_Read( psText, iLen, f );
		psText[iLen] = '\0';
		ri.FS_FCloseFile( f );

		AnimationCFGs[psCFGFilename] = psText;
	}

	if (psText)	// sanity, but should always be NZ
	{
		if (psDest)
		{
			Q_strncpyz(psDest,psText,iDestSize);
		}

		return strlen(psText);
	}

	return 0;
}
Exemplo n.º 12
0
// returns qtrue if loaded, and sets the supplied qbool to true if it was from cache (instead of disk)
//   (which we need to know to avoid LittleLong()ing everything again (well, the Mac needs to know anyway)...
//
qboolean RE_RegisterModels_GetDiskFile( const char *psModelFileName, void **ppvBuffer, qboolean *pqbAlreadyCached)
{
	char sModelName[MAX_QPATH];

	Q_strncpyz(sModelName,psModelFileName,sizeof(sModelName));
	Q_strlwr  (sModelName);

	CachedEndianedModelBinary_t &ModelBin = (*CachedModels)[sModelName];

	if (ModelBin.pModelDiskImage == NULL)
	{
		// didn't have it cached, so try the disk...
		//

			// special case intercept first...
			//
			if (!strcmp(sDEFAULT_GLA_NAME ".gla" , psModelFileName))
			{
				// return fake params as though it was found on disk...
				//
				void *pvFakeGLAFile = R_Malloc( sizeof(FakeGLAFile), TAG_FILESYS, qfalse );
				memcpy(pvFakeGLAFile, &FakeGLAFile[0],  sizeof(FakeGLAFile));
				*ppvBuffer = pvFakeGLAFile;
				*pqbAlreadyCached = qfalse;	// faking it like this should mean that it works fine on the Mac as well
				return qtrue;
			}

		ri.FS_ReadFile( sModelName, ppvBuffer );
		*pqbAlreadyCached = qfalse;

		return (qboolean)(*ppvBuffer != 0);
	}
	else
	{
		*ppvBuffer = ModelBin.pModelDiskImage;
		*pqbAlreadyCached = qtrue;
		return qtrue;
	}
}
Exemplo n.º 13
0
/*
================
IMG_Load
================
*/
void IMG_Load(image_t *image, byte *pic)
{
    int     i, c, b;
    int     width, height;

    width = image->upload_width;
    height = image->upload_height;

    if (image->flags & IF_TURBULENT) {
        image->width = TURB_SIZE;
        image->height = TURB_SIZE;
    }

    b = image->width * image->height;
    c = width * height;

    if (image->type == IT_WALL) {
        image->pixels[0] = R_Malloc(MIPSIZE(b) * TEX_BYTES);
        image->pixels[1] = image->pixels[0] + b * TEX_BYTES;
        image->pixels[2] = image->pixels[1] + b * TEX_BYTES / 4;
        image->pixels[3] = image->pixels[2] + b * TEX_BYTES / 16;

        if (!(r_config.flags & QVF_GAMMARAMP))
            R_LightScaleTexture(pic, width, height);

        if (width == image->width && height == image->height) {
            memcpy(image->pixels[0], pic, width * height * TEX_BYTES);
        } else {
            IMG_ResampleTexture(pic, width, height, image->pixels[0], image->width, image->height);
            image->upload_width = image->width;
            image->upload_height = image->height;
        }

        IMG_MipMap(image->pixels[1], image->pixels[0], image->width >> 0, image->height >> 0);
        IMG_MipMap(image->pixels[2], image->pixels[1], image->width >> 1, image->height >> 1);
        IMG_MipMap(image->pixels[3], image->pixels[2], image->width >> 2, image->height >> 2);

        Z_Free(pic);
    } else {
Exemplo n.º 14
0
/*
===============
ParseTriSurf
===============
*/
static void ParseTriSurf( dsurface_t *ds, mapVert_t *verts, msurface_t *surf, int *indexes, world_t &worldData, int index ) {
	srfTriangles_t	*tri;
	int				i, j, k;
	int				numVerts, numIndexes;

	// get fog volume
	surf->fogIndex = LittleLong( ds->fogNum ) + 1;
	if (index && !surf->fogIndex && tr.world && tr.world->globalFog != -1)
	{
		surf->fogIndex = worldData.globalFog;
	}

	// get shader
	surf->shader = ShaderForShaderNum( ds->shaderNum, lightmapsVertex, ds->lightmapStyles, ds->vertexStyles, worldData );
	if ( r_singleShader->integer && !surf->shader->sky ) {
		surf->shader = tr.defaultShader;
	}

	numVerts = LittleLong( ds->numVerts );
	numIndexes = LittleLong( ds->numIndexes );

	if ( numVerts >= SHADER_MAX_VERTEXES ) {
		Com_Error(ERR_DROP, "ParseTriSurf: verts > MAX (%d > %d) on misc_model %s", numVerts, SHADER_MAX_VERTEXES, surf->shader->name );
	}
	if ( numIndexes >= SHADER_MAX_INDEXES ) {
		Com_Error(ERR_DROP, "ParseTriSurf: indices > MAX (%d > %d) on misc_model %s", numIndexes, SHADER_MAX_INDEXES, surf->shader->name );
	}

	tri = (srfTriangles_t *) R_Malloc( sizeof( *tri ) + numVerts * sizeof( tri->verts[0] ) + numIndexes * sizeof( tri->indexes[0] ), TAG_HUNKMISCMODELS, qfalse );
	tri->dlightBits = 0; //JIC
	tri->surfaceType = SF_TRIANGLES;
	tri->numVerts = numVerts;
	tri->numIndexes = numIndexes;
	tri->verts = (drawVert_t *)(tri + 1);
	tri->indexes = (int *)(tri->verts + tri->numVerts );

	surf->data = (surfaceType_t *)tri;

	// copy vertexes
	verts += LittleLong( ds->firstVert );
	ClearBounds( tri->bounds[0], tri->bounds[1] );
	for ( i = 0 ; i < numVerts ; i++ ) {
		for ( j = 0 ; j < 3 ; j++ ) {
			tri->verts[i].xyz[j] = LittleFloat( verts[i].xyz[j] );
			tri->verts[i].normal[j] = LittleFloat( verts[i].normal[j] );
		}
		AddPointToBounds( tri->verts[i].xyz, tri->bounds[0], tri->bounds[1] );
		for ( j = 0 ; j < 2 ; j++ ) {
			tri->verts[i].st[j] = LittleFloat( verts[i].st[j] );
			for(k=0;k<MAXLIGHTMAPS;k++)
			{
				tri->verts[i].lightmap[k][j] = LittleFloat( verts[i].lightmap[k][j] );
			}
		}
		for(k=0;k<MAXLIGHTMAPS;k++)
		{
			R_ColorShiftLightingBytes( verts[i].color[k], tri->verts[i].color[k] );
		}
	}

	// copy indexes
	indexes += LittleLong( ds->firstIndex );
	for ( i = 0 ; i < numIndexes ; i++ ) {
		tri->indexes[i] = LittleLong( indexes[i] );
		if ( tri->indexes[i] < 0 || tri->indexes[i] >= numVerts ) {
			Com_Error( ERR_DROP, "Bad index in triangle surface" );
		}
	}
}
Exemplo n.º 15
0
void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height ) {
	/* This struct contains the JPEG decompression parameters and pointers to
	* working space (which is allocated as needed by the JPEG library).
	*/
	struct jpeg_decompress_struct cinfo = { NULL };
	/* We use our private extension JPEG error handler.
	* Note that this struct must live as long as the main JPEG parameter
	* struct, to avoid dangling-pointer problems.
	*/
	/* This struct represents a JPEG error handler.  It is declared separately
	* because applications often want to supply a specialized error handler
	* (see the second half of this file for an example).  But here we just
	* take the easy way out and use the standard error handler, which will
	* print a message on stderr and call exit() if compression fails.
	* Note that this struct must live as long as the main JPEG parameter
	* struct, to avoid dangling-pointer problems.
	*/
	struct jpeg_error_mgr jerr;
	/* More stuff */
	JSAMPARRAY buffer;		/* Output row buffer */
	unsigned int row_stride;  /* physical row width in output buffer */
	unsigned int pixelcount, memcount;
	unsigned int sindex, dindex;
	byte *out;
	union {
		byte *b;
		void *v;
	} fbuffer;
	byte  *buf;
	/* In this example we want to open the input file before doing anything else,
	* so that the setjmp() error recovery below can assume the file is open.
	* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
	* requires it in order to read binary files.
	*/

	int len = ri.FS_ReadFile ( ( char * ) filename, &fbuffer.v);
	if (!fbuffer.b || len < 0) {
		return;
	}

	/* Step 1: allocate and initialize JPEG decompression object */

	/* We have to set up the error handler first, in case the initialization
	* step fails.  (Unlikely, but it could happen if you are out of memory.)
	* This routine fills in the contents of struct jerr, and returns jerr's
	* address which we place into the link field in cinfo.
	*/
	cinfo.err = jpeg_std_error(&jerr);
	cinfo.err->error_exit = R_JPGErrorExit;
	cinfo.err->output_message = R_JPGOutputMessage;

	/* Now we can initialize the JPEG decompression object. */
	jpeg_create_decompress(&cinfo);

	/* Step 2: specify data source (eg, a file) */

	jpeg_mem_src(&cinfo, fbuffer.b, len);

	/* Step 3: read file parameters with jpeg_read_header() */

	(void) jpeg_read_header(&cinfo, TRUE);
	/* We can ignore the return value from jpeg_read_header since
	*   (a) suspension is not possible with the stdio data source, and
	*   (b) we passed TRUE to reject a tables-only JPEG file as an error.
	* See libjpeg.doc for more info.
	*/

	/* Step 4: set parameters for decompression */


	/* Make sure it always converts images to RGB color space. This will
	* automatically convert 8-bit greyscale images to RGB as well.	*/
	cinfo.out_color_space = JCS_RGB;

	/* Step 5: Start decompressor */

	(void) jpeg_start_decompress(&cinfo);
	/* We can ignore the return value since suspension is not possible
	* with the stdio data source.
	*/

	/* We may need to do some setup of our own at this point before reading
	* the data.  After jpeg_start_decompress() we have the correct scaled
	* output image dimensions available, as well as the output colormap
	* if we asked for color quantization.
	* In this example, we need to make an output work buffer of the right size.
	*/
	/* JSAMPLEs per row in output buffer */
	pixelcount = cinfo.output_width * cinfo.output_height;

	if(!cinfo.output_width || !cinfo.output_height
		|| ((pixelcount * 4) / cinfo.output_width) / 4 != cinfo.output_height
		|| pixelcount > 0x1FFFFFFF || cinfo.output_components != 3
		)
	{
		// Free the memory to make sure we don't leak memory
		ri.FS_FreeFile (fbuffer.v);
		jpeg_destroy_decompress(&cinfo);

		ri.Printf( PRINT_ALL, "LoadJPG: %s has an invalid image format: %dx%d*4=%d, components: %d", filename,
			cinfo.output_width, cinfo.output_height, pixelcount * 4, cinfo.output_components);
		return;
	}

	memcount = pixelcount * 4;
	row_stride = cinfo.output_width * cinfo.output_components;

	out = (byte *)R_Malloc(memcount, TAG_TEMP_WORKSPACE, qfalse);

	*width = cinfo.output_width;
	*height = cinfo.output_height;

	/* Step 6: while (scan lines remain to be read) */
	/*           jpeg_read_scanlines(...); */

	/* Here we use the library's state variable cinfo.output_scanline as the
	* loop counter, so that we don't have to keep track ourselves.
	*/
	while (cinfo.output_scanline < cinfo.output_height) {
		/* jpeg_read_scanlines expects an array of pointers to scanlines.
		* Here the array is only one element long, but you could ask for
		* more than one scanline at a time if that's more convenient.
		*/
		buf = ((out+(row_stride*cinfo.output_scanline)));
		buffer = &buf;
		(void) jpeg_read_scanlines(&cinfo, buffer, 1);
	}

	buf = out;
	// Expand from RGB to RGBA
	sindex = pixelcount * cinfo.output_components;
	dindex = memcount;

	do {
		buf[--dindex] = 255;
		buf[--dindex] = buf[--sindex];
		buf[--dindex] = buf[--sindex];
		buf[--dindex] = buf[--sindex];
	} while(sindex);

	*pic = out;

	/* Step 7: Finish decompression */

	(void) jpeg_finish_decompress(&cinfo);
	/* We can ignore the return value since suspension is not possible
	* with the stdio data source.
	*/

	/* Step 8: Release JPEG decompression object */

	/* This is an important step since it will release a good deal of memory. */
	jpeg_destroy_decompress(&cinfo);

	/* After finish_decompress, we can close the input file.
	* Here we postpone it until after no more JPEG errors are possible,
	* so as to simplify the setjmp error logic above.  (Actually, I don't
	* think that jpeg_destroy can do an error exit, but why assume anything...)
	*/
	ri.FS_FreeFile (fbuffer.v);
	/* At this point you may want to check to see whether any corrupt-data
	* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
	*/

	/* And we're done! */
}
Exemplo n.º 16
0
/*
* R_StartCinematic
*/
unsigned int R_StartCinematic( const char *arg ) {
	char uploadName[128];
	size_t name_size;
	char *name;
	r_cinhandle_t *handle, *hnode, *next;
	struct cinematics_s *cin;
	bool yuv;

	name_size = strlen( "video/" ) + strlen( arg ) + 1;
	name = alloca( name_size );

	if( strstr( arg, "/" ) == NULL && strstr( arg, "\\" ) == NULL ) {
		Q_snprintfz( name, name_size, "video/%s", arg );
	} else {
		Q_snprintfz( name, name_size, "%s", arg );
	}

	// find cinematics with the same name
	hnode = &r_cinematics_headnode;
	for( handle = hnode->prev; handle != hnode; handle = next ) {
		next = handle->prev;
		assert( handle->cin );

		// reuse
		if( !Q_stricmp( handle->name, name ) ) {
			return handle->id;
		}
	}

	// open the file, read header, etc
	cin = ri.CIN_Open( name, ri.Sys_Milliseconds(), &yuv, NULL );

	// take a free cinematic handle if possible
	if( !r_free_cinematics || !cin ) {
		return 0;
	}

	handle = r_free_cinematics;
	r_free_cinematics = handle->next;

	// copy name
	handle->name = R_CopyString( name );

	// copy upload name
	Q_snprintfz( uploadName, sizeof( uploadName ), "***r_cinematic%i***", handle->id - 1 );
	name_size = strlen( uploadName ) + 1;
	handle->uploadName = R_Malloc( name_size );
	memcpy( handle->uploadName, uploadName, name_size );

	handle->cin = cin;
	handle->new_frame = false;
	handle->yuv = yuv;
	handle->image = NULL;
	handle->yuv_images[0] = handle->yuv_images[1] = handle->yuv_images[2] = NULL;
	handle->registrationSequence = rsh.registrationSequence;
	handle->pic = NULL;
	handle->cyuv = NULL;
	handle->lock = ri.Mutex_Create();

	// put handle at the start of the list
	handle->prev = &r_cinematics_headnode;
	handle->next = r_cinematics_headnode.next;
	handle->next->prev = handle;
	handle->prev->next = handle;

	return handle->id;
}