1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 #include "globalincs/pstypes.h"
13 #include "bmpman/bmpman.h"
14 #include "ddsutils/ddsutils.h"
15 #include "tgautils/tgautils.h"
16 #include "pngutils/pngutils.h"
17 #include "jpgutils/jpgutils.h"
18 #include "pcxutils/pcxutils.h"
19 #include "graphics/gropengltexture.h"
20 #include "graphics/gropenglextension.h"
21 #include "globalincs/systemvars.h"
22 #include "anim/animplay.h"
23 #include "anim/packunpack.h"
24 #include "cmdline/cmdline.h"
25 
26 #define BMPMAN_INTERNAL
27 #include "bmpman/bm_internal.h"
28 
29 
30 
is_power_of_two(int w,int h)31 static inline int is_power_of_two(int w, int h)
32 {
33 	// NOTE: OpenGL texture code has a min tex size of 16 (currently), so we need to be at least
34 	//       the min size here to qualify as power-of-2 and not get resized later on
35 	return ( ((w >= GL_min_texture_width) && !(w & (w-1))) && ((h >= GL_min_texture_height) && !(h & (h-1))) );
36 }
37 
get_num_mipmap_levels(int w,int h)38 int get_num_mipmap_levels(int w, int h)
39 {
40 	int size, levels = 0;
41 
42 	// make sure we can and should generate mipmaps before trying to use them
43 	if ( !Cmdline_mipmap || !Is_Extension_Enabled(OGL_SGIS_GENERATE_MIPMAP) )
44 		return 1;
45 
46 	size = MAX(w, h);
47 
48 	while (size > 0) {
49 		size >>= 1;
50 		levels++;
51 	}
52 
53 	return (levels > 1) ? levels : 1;
54 }
55 
56 /**
57  * Anything API specific to freeing bm data
58  */
gr_opengl_bm_free_data(int n,bool release)59 void gr_opengl_bm_free_data(int n, bool release)
60 {
61 	Assert( (n >= 0) && (n < MAX_BITMAPS) );
62 
63 	// might as well free up the on card texture data too in order to get rid
64 	// of old interface stuff but don't free USER types, unless it's a total release,
65 	// since we can reuse ANI slots for faster and less resource intensive rendering
66 	if ( release || (bm_bitmaps[n].type != BM_TYPE_USER) )
67 		opengl_free_texture_slot( n );
68 
69 	if ( (bm_bitmaps[n].type == BM_TYPE_RENDER_TARGET_STATIC) || (bm_bitmaps[n].type == BM_TYPE_RENDER_TARGET_DYNAMIC) )
70 		opengl_kill_render_target( n );
71 }
72 
73 /**
74  * API specifics for creating a user bitmap
75  */
gr_opengl_bm_create(int n)76 void gr_opengl_bm_create(int n)
77 {
78 	Assert( (n >= 0) && (n < MAX_BITMAPS) );
79 }
80 
81 // Load an image and validate it while retrieving information for later use
82 // Input:	type		= current BM_TYPE_*
83 //			n			= location in bm_bitmaps[]
84 //			filename	= name of the current file
85 //			img_cfp		= already open CFILE handle, if available
86 //
87 // Output:	w			= bmp width
88 //			h			= bmp height
89 //			bpp			= bmp bits per pixel
90 //			c_type		= output for an updated BM_TYPE_*
91 //			mm_lvl		= number of mipmap levels for the image
92 //			size		= size of the data contained in the image
gr_opengl_bm_load(ubyte type,int n,const char * filename,CFILE * img_cfp,int * w,int * h,int * bpp,ubyte * c_type,int * mm_lvl,int * size)93 int gr_opengl_bm_load(ubyte type, int n, const char *filename, CFILE *img_cfp, int *w, int *h, int *bpp, ubyte *c_type, int *mm_lvl, int *size)
94 {
95 	int dds_ct;
96 
97 	if (type == BM_TYPE_DDS) {
98 		int dds_error = dds_read_header( filename, img_cfp, w, h, bpp, &dds_ct, mm_lvl, size );
99 
100 		if (dds_error != DDS_ERROR_NONE) {
101 			mprintf(("DDS ERROR: Couldn't open '%s' -- %s\n", filename, dds_error_string(dds_error)));
102 			return -1;
103 		}
104 
105 		switch (dds_ct) {
106 			case DDS_DXT1:
107 				*c_type = BM_TYPE_DXT1;
108 				break;
109 
110 			case DDS_DXT3:
111 				*c_type = BM_TYPE_DXT3;
112 				break;
113 
114 			case DDS_DXT5:
115 				*c_type = BM_TYPE_DXT5;
116 				break;
117 
118 			case DDS_UNCOMPRESSED:
119 				*c_type = BM_TYPE_DDS;
120 				break;
121 
122 			case DDS_CUBEMAP_DXT1:
123 				*c_type = BM_TYPE_CUBEMAP_DXT1;
124 				break;
125 
126 			case DDS_CUBEMAP_DXT3:
127 				*c_type = BM_TYPE_CUBEMAP_DXT3;
128 				break;
129 
130 			case DDS_CUBEMAP_DXT5:
131 				*c_type = BM_TYPE_CUBEMAP_DXT5;
132 				break;
133 
134 			case DDS_CUBEMAP_UNCOMPRESSED:
135 				*c_type = BM_TYPE_CUBEMAP_DDS;
136 				break;
137 
138 			default:
139 				Error(LOCATION, "Bad DDS file compression! Not using DXT1,3,5: %s", filename);
140 				return -1;
141 		}
142 	}
143 	// if its a tga file
144 	else if (type == BM_TYPE_TGA) {
145 		int tga_error = targa_read_header( filename, img_cfp, w, h, bpp, NULL );
146 		if ( tga_error != TARGA_ERROR_NONE )	{
147 			mprintf(( "tga: Couldn't open '%s'\n", filename ));
148 			return -1;
149 		}
150 	}
151 	// if its a png file
152  	else if (type == BM_TYPE_PNG) {
153  		int png_error=png_read_header( filename, img_cfp, w, h, bpp, NULL );
154  		if ( png_error != PNG_ERROR_NONE ) {
155  			mprintf(( "png: Couldn't open '%s'\n", filename ));
156  			return -1;
157  		}
158  	}
159 	// if its a jpg file
160 	else if (type == BM_TYPE_JPG) {
161 		int jpg_error=jpeg_read_header( filename, img_cfp, w, h, bpp, NULL );
162 		if ( jpg_error != JPEG_ERROR_NONE ) {
163 			mprintf(( "jpg: Couldn't open '%s'\n", filename ));
164 			return -1;
165 		}
166 	}
167 	// if its a pcx file
168 	else if (type == BM_TYPE_PCX) {
169 		int pcx_error = pcx_read_header( filename, img_cfp, w, h, bpp, NULL );
170 		if ( pcx_error != PCX_ERROR_NONE )	{
171 			mprintf(( "pcx: Couldn't open '%s'\n", filename ));
172 			return -1;
173 		}
174 	} else {
175 		Assert( 0 );
176 
177 		return -1;
178 	}
179 
180 	return 0;
181 }
182 
183 /**
184  * API specific init instructions
185  */
gr_opengl_bm_init(int n)186 void gr_opengl_bm_init(int n)
187 {
188 	Assert( (n >= 0) && (n < MAX_BITMAPS) );
189 }
190 
191 /**
192  * Specific instructions for setting up the start of a page-in session
193  */
gr_opengl_bm_page_in_start()194 void gr_opengl_bm_page_in_start()
195 {
196 	opengl_preload_init();
197 }
198 
199 extern void bm_clean_slot(int n);
200 extern int opengl_compress_image( ubyte **out_data, ubyte *in_data, int width, int height, int alpha = 1, int num_mipmaps = 1 );
201 
opengl_bm_lock_ani_compress(int handle,int bitmapnum,bitmap_entry * be,bitmap * bmp,ubyte bpp,ubyte flags)202 static int opengl_bm_lock_ani_compress( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags )
203 {
204 	anim			*the_anim;
205 	anim_instance	*the_anim_instance;
206 	bitmap			*bm;
207 	ubyte			*frame_data;
208 	int				size, i;
209 	int				first_frame, nframes;
210 	ubyte *compressed_data = NULL;
211 	int out_size = 0;
212 	int alpha = 0;
213 	int num_mipmaps = 1;
214 
215 	first_frame = be->info.ani.first_frame;
216 	nframes = bm_bitmaps[first_frame].info.ani.num_frames;
217 
218 	// bpp can always be 24-bit since we don't do images with alpha here
219 	bpp = 24;
220 
221 	alpha = (bpp == 32);
222 
223 	if ( (the_anim = anim_load(bm_bitmaps[first_frame].filename, bm_bitmaps[first_frame].dir_type)) == NULL ) {
224 		nprintf(("BMPMAN", "Error opening %s in bm_lock\n", be->filename));
225 		return 1;
226 	}
227 
228 	if ( (the_anim_instance = init_anim_instance(the_anim, bpp)) == NULL ) {
229 		nprintf(("BMPMAN", "Error opening %s in bm_lock\n", be->filename));
230 		anim_free(the_anim);
231 		return 1;
232 	}
233 
234 	int can_drop_frames = 0;
235 
236 	if ( the_anim->total_frames != bm_bitmaps[first_frame].info.ani.num_frames )	{
237 		can_drop_frames = 1;
238 	}
239 
240 	bm = &bm_bitmaps[first_frame].bm;
241 	size = bm->w * bm->h * (bpp >> 3);
242 
243 	num_mipmaps = get_num_mipmap_levels( bm->w, bm->h );
244 	Assert( num_mipmaps > 0 );
245 
246 	nprintf(("BMPMAN", "Attempting to compress '%s' with %d frames, original size %.3fM ... ", bm_bitmaps[first_frame].filename, nframes, ((float)(size*nframes)/1024.0f)/1024.0f));
247 
248 	for ( i=0; i<nframes; i++ )	{
249 		be = &bm_bitmaps[first_frame+i];
250 		bmp = &bm_bitmaps[first_frame+i].bm;
251 
252 		// Unload any existing data
253 		bm_clean_slot( first_frame+i );
254 
255 		bmp->flags = 0;
256 
257 		bmp->bpp = bpp;
258 
259 		frame_data = anim_get_next_raw_buffer(the_anim_instance, 0, 0, bmp->bpp);
260 
261 		Assert( frame_data != NULL );
262 
263 		out_size = opengl_compress_image(&compressed_data, frame_data, bmp->w, bmp->h, alpha, num_mipmaps);
264 
265 		if (out_size == 0) {
266 			if (compressed_data != NULL) {
267 				vm_free(compressed_data);
268 				compressed_data = NULL;
269 			}
270 
271 			nprintf(("BMPMAN", "compression failed!!\n"));
272 
273 			return 1;
274 		}
275 
276 		Assert( compressed_data != NULL );
277 
278 		bmp->data = (ptr_u)compressed_data;
279 		bmp->bpp = (alpha) ? 32 : 24;
280 		bmp->palette = NULL;
281 		be->comp_type = (alpha) ? BM_TYPE_DXT5 : BM_TYPE_DXT1;
282 		be->mem_taken = out_size;
283 		be->num_mipmaps = num_mipmaps;
284 
285 		bm_update_memory_used( first_frame + i, out_size );
286 
287 		// Skip a frame
288 		if ( (i < nframes-1)  && can_drop_frames )	{
289 			frame_data = anim_get_next_raw_buffer(the_anim_instance, 0, 0, bm->bpp);
290 		}
291 
292 		compressed_data = NULL;
293 	}
294 
295 	if (num_mipmaps > 1) {
296 		nprintf(("BMPMAN", "new size is %.3fM with %d mipmap levels.\n", ((float)(out_size*nframes)/1024.0f)/1024.0f, num_mipmaps));
297 	} else {
298 		nprintf(("BMPMAN", "new size is %.3fM.\n", ((float)(out_size*nframes)/1024.0f)/1024.0f));
299 	}
300 
301 	free_anim_instance(the_anim_instance);
302 	anim_free(the_anim);
303 
304 	return 0;
305 }
306 
opengl_bm_lock_compress(int handle,int bitmapnum,bitmap_entry * be,bitmap * bmp,int bpp,int flags)307 static int opengl_bm_lock_compress( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, int flags )
308 {
309 	ubyte *data = NULL;
310 	ubyte *compressed_data = NULL;
311 	int error_code = 1;
312 	int out_size = 0;
313 	int byte_size = 0;
314 	int alpha = 1;
315 	int num_mipmaps = 1;
316 
317 	// don't use for EFFs, if they were wanting to be DDS then they should already be that way
318 	if ( be->type == BM_TYPE_EFF ) {
319 		return 1;
320 	}
321 
322 	Assert( (be->type == BM_TYPE_PCX) ||
323 			(be->type == BM_TYPE_TGA) ||
324 			(be->type == BM_TYPE_PNG) ||
325 			(be->type == BM_TYPE_JPG) );
326 
327 	Assert( !(flags & BMP_AABITMAP) );
328 
329 	// PCX need to be loaded as 32-bit
330 	if ( (be->type == BM_TYPE_PCX) && (bpp == 16) )
331 		bpp = 32;
332 
333 	bm_clean_slot( bitmapnum );
334 
335 	byte_size = (bpp >> 3);
336 	Assert( (byte_size == 3) || (byte_size == 4) );
337 	alpha = (byte_size != 3);
338 
339 	data = (ubyte*)vm_malloc(bmp->w * bmp->h * byte_size);
340 
341 	Assert( data != NULL );
342 
343 	if ( data == NULL )
344 		return 1;
345 
346 	// read in bitmap data
347 	if (be->type == BM_TYPE_PCX) {
348 		Assert( bpp == 32 );
349 		error_code = pcx_read_bitmap( be->filename, data, NULL, byte_size );
350 	} else if (be->type == BM_TYPE_TGA) {
351 		error_code = targa_read_bitmap( be->filename, data, NULL, byte_size );
352  	} else if (be->type == BM_TYPE_PNG) {
353  		error_code = png_read_bitmap( be->filename, data, NULL, byte_size );
354 	} else if (be->type == BM_TYPE_JPG) {
355 		error_code = jpeg_read_bitmap( be->filename, data, NULL, byte_size );
356 	} else {
357 		Assert( 0 );
358 	}
359 
360 	nprintf(("BMPMAN", "Attempting to compress '%s', original size %.3fM ... ", be->filename, ((float)(bmp->w * bmp->h * byte_size)/1024.0f)/1024.0f));
361 
362 	// NOTE: this assumes that the *_ERROR_NONE #define's are going to be 0
363 	if (error_code) {
364 		if (data != NULL) {
365 			vm_free(data);
366 			data = NULL;
367 		}
368 
369 		nprintf(("BMPMAN", "initial read failed!!\n"));
370 
371 		return 1;
372 	}
373 
374 	num_mipmaps = get_num_mipmap_levels( bmp->w, bmp->h );
375 	Assert( num_mipmaps > 0 );
376 
377 	// now for the attempt to compress the data
378 	out_size = opengl_compress_image(&compressed_data, data, bmp->w, bmp->h, alpha, num_mipmaps);
379 
380 	if (data != NULL) {
381 		vm_free(data);
382 		data = NULL;
383 	}
384 
385 	if (out_size == 0) {
386 		if (compressed_data != NULL) {
387 			vm_free(compressed_data);
388 			compressed_data = NULL;
389 		}
390 
391 		nprintf(("BMPMAN", "compression failed!!\n"));
392 
393 		return 1;
394 	}
395 
396 	Assert( compressed_data != NULL );
397 
398 	if (num_mipmaps > 1) {
399 		nprintf(("BMPMAN", "new size is %.3fM with %d mipmap levels.\n", ((float)out_size/1024.0f)/1024.0f, num_mipmaps));
400 	} else {
401 		nprintf(("BMPMAN", "new size is %.3fM.\n", ((float)out_size/1024.0f)/1024.0f));
402 	}
403 
404 	bmp->data = (ptr_u)compressed_data;
405 	bmp->bpp = (alpha) ? (ubyte)32 : (ubyte)24;
406 	bmp->palette = NULL;
407 	be->comp_type = (alpha) ? BM_TYPE_DXT5 : BM_TYPE_DXT1;
408 	be->mem_taken = out_size;
409 	be->num_mipmaps = num_mipmaps;
410 
411 	bm_update_memory_used( bitmapnum, out_size );
412 
413 	return 0;
414 }
415 
416 extern bool opengl_texture_slot_valid(int n, int handle);
417 
418 /**
419  * Lock an image files data into memory
420  */
gr_opengl_bm_lock(const char * filename,int handle,int bitmapnum,ubyte bpp,ubyte flags,bool nodebug)421 int gr_opengl_bm_lock( const char *filename, int handle, int bitmapnum, ubyte bpp, ubyte flags, bool nodebug)
422 {
423 	ubyte c_type = BM_TYPE_NONE;
424 	ubyte true_bpp;
425 	int try_compress = 0;
426 
427 	bitmap_entry *be = &bm_bitmaps[bitmapnum];
428 	bitmap *bmp = &be->bm;
429 
430 	Assert( !Is_standalone );
431 
432 	if (bmp->true_bpp > bpp)
433 		true_bpp = bmp->true_bpp;
434 	else
435 		true_bpp = bpp;
436 
437 	// don't do a bpp check here since it could be different in OGL - taylor
438 	if ( (bmp->data == 0) && !opengl_texture_slot_valid(bitmapnum, handle) ) {
439 		Assert(be->ref_count == 1);
440 
441 		if (be->type != BM_TYPE_USER && !nodebug) {
442 			if (bmp->data == 0)
443 				nprintf (("BmpMan", "Loading %s for the first time.\n", be->filename));
444 		}
445 
446 		if ( !Bm_paging )	{
447 			if (be->type != BM_TYPE_USER && !nodebug)
448 				nprintf(("Paging", "Loading %s (%dx%dx%d)\n", be->filename, bmp->w, bmp->h, true_bpp));
449 		}
450 
451 		// select proper format
452 		if (flags & BMP_AABITMAP)
453 			BM_SELECT_ALPHA_TEX_FORMAT();
454 		else if (flags & BMP_TEX_ANY)
455 			BM_SELECT_TEX_FORMAT();
456 		else
457 			BM_SELECT_SCREEN_FORMAT();
458 
459 		// make sure we use the real graphic type for EFFs
460 		if ( be->type == BM_TYPE_EFF ) {
461 			c_type = be->info.ani.eff.type;
462 		} else {
463 			c_type = be->type;
464 		}
465 
466 		try_compress = (Cmdline_img2dds && Texture_compression_available && is_power_of_two(bmp->w, bmp->h) && !(flags & BMP_AABITMAP) && !Is_standalone);
467 
468 		switch ( c_type )
469 		{
470 			case BM_TYPE_PCX:
471 				if (try_compress && (true_bpp >= 16)) {
472 					if ( !opengl_bm_lock_compress(handle, bitmapnum, be, bmp, true_bpp, flags) ) {
473 						break;
474 					}
475 				}
476 
477 				bm_lock_pcx( handle, bitmapnum, be, bmp, true_bpp, flags );
478 				break;
479 
480 			case BM_TYPE_ANI:
481 				if (try_compress && (true_bpp >= 16) && !(flags & BMP_TEX_XPARENT)) {
482 					if ( !opengl_bm_lock_ani_compress(handle, bitmapnum, be, bmp, true_bpp, flags) ) {
483 						break;
484 					}
485 				}
486 
487 				bm_lock_ani( handle, bitmapnum, be, bmp, true_bpp, flags );
488 				break;
489 
490 			case BM_TYPE_TGA:
491 				if (try_compress && (true_bpp >= 24)) {
492 					if ( !opengl_bm_lock_compress(handle, bitmapnum, be, bmp, true_bpp, flags) ) {
493 						break;
494 					}
495 				}
496 
497 				bm_lock_tga( handle, bitmapnum, be, bmp, true_bpp, flags );
498 				break;
499 
500  			case BM_TYPE_PNG:
501  				//libpng handles compression with zlib
502  				bm_lock_png( handle, bitmapnum, be, bmp, true_bpp, flags );
503  				break;
504 
505 			case BM_TYPE_JPG:
506 				if (try_compress) {
507 					if ( !opengl_bm_lock_compress(handle, bitmapnum, be, bmp, true_bpp, flags) ) {
508 						break;
509 					}
510 				}
511 
512 				bm_lock_jpg( handle, bitmapnum, be, bmp, true_bpp, flags );
513 				break;
514 
515 			case BM_TYPE_DDS:
516 			case BM_TYPE_DXT1:
517 			case BM_TYPE_DXT3:
518 			case BM_TYPE_DXT5:
519 			case BM_TYPE_CUBEMAP_DDS:
520 			case BM_TYPE_CUBEMAP_DXT1:
521 			case BM_TYPE_CUBEMAP_DXT3:
522 			case BM_TYPE_CUBEMAP_DXT5:
523 				bm_lock_dds( handle, bitmapnum, be, bmp, true_bpp, flags );
524 				break;
525 
526 			case BM_TYPE_USER:
527 				bm_lock_user( handle, bitmapnum, be, bmp, true_bpp, flags );
528 				break;
529 
530 			default:
531 				Warning(LOCATION, "Unsupported type in bm_lock -- %d\n", c_type );
532 				return -1;
533 		}
534 
535 		// always go back to screen format
536 		BM_SELECT_SCREEN_FORMAT();
537 
538 		// make sure we actually did something
539 		if ( !(bmp->data) )
540 			return -1;
541 	}
542 
543 	return 0;
544 }
545 
gr_opengl_bm_save_render_target(int n)546 void gr_opengl_bm_save_render_target(int n)
547 {
548 	Assert( (n >= 0) && (n < MAX_BITMAPS) );
549 
550 	if ( !Is_Extension_Enabled(OGL_EXT_FRAMEBUFFER_OBJECT) || Cmdline_no_fbo ) {
551 		return;
552 	}
553 
554 	bitmap_entry *be = &bm_bitmaps[n];
555 	bitmap *bmp = &be->bm;
556 
557 	int rc = opengl_export_image(n, bmp->w, bmp->h, (bmp->true_bpp == 32), be->num_mipmaps, (ubyte*)bmp->data);
558 
559 	if (rc != be->mem_taken) {
560 		Int3();
561 		return;
562 	}
563 
564 	if (Cmdline_save_render_targets) {
565 		dds_save_image(bmp->w, bmp->h, bmp->true_bpp, be->num_mipmaps, (ubyte*)bmp->data, (bmp->flags & BMP_FLAG_CUBEMAP));
566 	}
567 }
568 
gr_opengl_bm_make_render_target(int n,int * width,int * height,ubyte * bpp,int * mm_lvl,int flags)569 int gr_opengl_bm_make_render_target(int n, int *width, int *height, ubyte *bpp, int *mm_lvl, int flags)
570 {
571 	Assert( (n >= 0) && (n < MAX_BITMAPS) );
572 
573 	if ( !Is_Extension_Enabled(OGL_EXT_FRAMEBUFFER_OBJECT) || Cmdline_no_fbo ) {
574 		return 0;
575 	}
576 
577 	if ( (flags & BMP_FLAG_CUBEMAP) && !Is_Extension_Enabled(OGL_ARB_TEXTURE_CUBE_MAP) ) {
578 		return 0;
579 	}
580 
581 	if ( (flags & BMP_FLAG_CUBEMAP) && (*width != *height) ) {
582 		MIN(*width, *height) = MAX(*width, *height);
583 	}
584 
585 	// Only enforce power of two size if not supported
586 	if (!(Is_Extension_Enabled(OGL_ARB_TEXTURE_NON_POWER_OF_TWO)))
587 	{
588 		Assert( is_power_of_two(*width, *height) );
589 	}
590 
591 	if ( opengl_make_render_target(bm_bitmaps[n].handle, n, width, height, bpp, mm_lvl, flags) ) {
592 		return 1;
593 	}
594 
595 	return 0;
596 }
597 
gr_opengl_bm_set_render_target(int n,int face)598 int gr_opengl_bm_set_render_target(int n, int face)
599 {
600 	if ( !Is_Extension_Enabled(OGL_EXT_FRAMEBUFFER_OBJECT) || Cmdline_no_fbo ) {
601 		return 0;
602 	}
603 
604 	if (n == -1) {
605 		opengl_set_render_target(-1);
606 		return 1;
607 	}
608 
609 	Assert( (n >= 0) && (n < MAX_BITMAPS) );
610 
611 	int is_static = (bm_bitmaps[n].type == BM_TYPE_RENDER_TARGET_STATIC);
612 
613 	if ( opengl_set_render_target(n, face, is_static) ) {
614 		return 1;
615 	}
616 
617 	return 0;
618 }
619