1 /*
2 Copyright (C) 2007, 2010 - Bit-Blot
3 
4 This file is part of Aquaria.
5 
6 Aquaria is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 
15 See the GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */
21 #include "Texture.h"
22 #include "Core.h"
23 #include "../ExternalLibs/glpng.h"
24 #include "ByteBuffer.h"
25 
26 #include <assert.h>
27 
28 #if defined(BBGE_BUILD_UNIX)
29 #include <stdint.h>
30 #endif
31 
32 //#include "pngLoad.h"
33 //#include "jpeg/jpeglib.h"
34 /*
35 #include <il/il.h>
36 #include <il/ilu.h>
37 #include <il/ilut.h>
38 */
39 #ifdef Z2D_J2K
40 //..\j2k-codec\j2k-codec.lib
41 	#include "..\j2k-codec\j2k-codec.h"
42 #endif
43 
44 #ifdef BBGE_BUILD_OPENGL
45 	GLint Texture::filter = GL_LINEAR;
46 
47 	GLint Texture::format = 0;
48 #endif
49 bool Texture::useMipMaps = true;
50 
51 /*
52 #ifdef BBGE_BUILD_OPENGL
53 #include "glext/glext.h"
54 #endif
55 */
56 
57 
Texture()58 Texture::Texture()
59 {
60 #ifdef BBGE_BUILD_OPENGL
61 	textures[0] = 0;
62 #endif
63 #ifdef BBGE_BUILD_DIRECTX
64 	d3dTexture = 0;
65 #endif
66 	width = height = 0;
67 
68 	repeat = false;
69 	repeating = false;
70 	pngSetStandardOrientation(0);
71 	ow = oh = -1;
72 }
73 
~Texture()74 Texture::~Texture()
75 {
76 	destroy();
77 }
78 
read(int tx,int ty,int w,int h,unsigned char * pixels)79 void Texture::read(int tx, int ty, int w, int h, unsigned char *pixels)
80 {
81 #ifdef BBGE_BUILD_OPENGL
82 	if (tx == 0 && ty == 0 && w == this->width && h == this->height)
83 	{
84 		glBindTexture(GL_TEXTURE_2D, textures[0]);
85 		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
86 		glBindTexture(GL_TEXTURE_2D, 0);
87 	}
88 	else
89 	{
90 		std::ostringstream os;
91 		os << "Unable to read a texture subimage (size = "
92 		   << this->width << "x" << this->height << ", requested = "
93 		   << tx << "," << ty << "+" << w << "x" << h << ")";
94 		debugLog(os.str());
95 	}
96 #endif
97 }
98 
write(int tx,int ty,int w,int h,const unsigned char * pixels)99 void Texture::write(int tx, int ty, int w, int h, const unsigned char *pixels)
100 {
101 #ifdef BBGE_BUILD_OPENGL
102 	glBindTexture(GL_TEXTURE_2D, textures[0]);
103 
104 	glTexSubImage2D(GL_TEXTURE_2D, 0,
105 					tx,
106 					ty,
107 					w,
108 					h,
109 					GL_RGBA,
110 					GL_UNSIGNED_BYTE,
111 					pixels
112 					);
113 
114 	glBindTexture(GL_TEXTURE_2D, 0);
115 	/*
116 	  target   Specifies the target	texture.  Must be
117 		   GL_TEXTURE_2D.
118 
119 	  level	   Specifies the level-of-detail number.  Level	0 is
120 		   the base image level.  Level	n is the nth mipmap
121 		   reduction image.
122 
123 	  xoffset  Specifies a texel offset in the x direction within
124 		   the texture array.
125 
126 	  yoffset  Specifies a texel offset in the y direction within
127 		   the texture array.
128 
129 	  width	   Specifies the width of the texture subimage.
130 
131 	  height   Specifies the height	of the texture subimage.
132 
133 	  format   Specifies the format	of the pixel data.  The
134 		   following symbolic values are accepted:
135 		   GL_COLOR_INDEX, GL_RED, GL_GREEN, GL_BLUE,
136 		   GL_ALPHA, GL_RGB, GL_RGBA, GL_LUMINANCE, and
137 		   GL_LUMINANCE_ALPHA.
138 
139 	  type	   Specifies the data type of the pixel	data.  The
140 		   following symbolic values are accepted:
141 		   GL_UNSIGNED_BYTE, GL_BYTE, GL_BITMAP,
142 		   GL_UNSIGNED_SHORT, GL_SHORT,	GL_UNSIGNED_INT,
143 		   GL_INT, and GL_FLOAT.
144 
145 	  pixels   Specifies a pointer to the image data in memory.
146 	  */
147 #endif
148 }
149 
unload()150 void Texture::unload()
151 {
152 #ifdef BBGE_BUILD_OPENGL
153 	if (textures[0])
154 	{
155 		ow = width;
156 		oh = height;
157 
158 		if (core->debugLogTextures)
159 		{
160 			debugLog("UNLOADING TEXTURE: " + name);
161 		}
162 
163 
164 		glDeleteTextures(1, &textures[0]);
165 		textures[0] = 0;
166 	}
167 #endif
168 }
169 
destroy()170 void Texture::destroy()
171 {
172 #ifdef BBGE_BUILD_OPENGL
173 	unload();
174 #endif
175 #ifdef BBGE_BUILD_DIRECTX
176 	if (d3dTexture)
177 	{
178 		d3dTexture->Release();
179 		d3dTexture = 0;
180 	}
181 #endif
182 
183 	core->removeTexture(this);
184 }
185 
getPixelWidth()186 int Texture::getPixelWidth()
187 {
188 #ifdef BBGE_BUILD_OPENGL
189 	int w = 0, h = 0;
190 	unsigned int size = 0;
191 	unsigned char *data = getBufferAndSize(&w, &h, &size);
192 	if (!data)
193 		return 0;
194 
195 	int smallestx = -1, largestx = -1;
196 	for (unsigned int x = 0; x < unsigned(w); x++)
197 	{
198 		for (unsigned int y = 0; y < unsigned(h); y++)
199 		{
200 			unsigned int p = (y*unsigned(w)*4) + (x*4) + 3;
201 			if (p < size && data[p] >= 254)
202 			{
203 				if (smallestx == -1 || x < smallestx)
204 					smallestx = x;
205 				if (largestx == -1 || x > largestx)
206 					largestx = x;
207 			}
208 		}
209 	}
210 	free(data);
211 	return largestx - smallestx;
212 #elif defined(BBGE_BUILD_DIRECTX)
213 	return 0;
214 #endif
215 }
216 
getPixelHeight()217 int Texture::getPixelHeight()
218 {
219 #ifdef BBGE_BUILD_OPENGL
220 	int w = 0, h = 0;
221 	unsigned int size = 0;
222 	unsigned char *data = getBufferAndSize(&w, &h, &size);
223 	if (!data)
224 		return 0;
225 
226 	int smallesty = -1, largesty = -1;
227 	for (unsigned int x = 0; x < unsigned(w); x++)
228 	{
229 		for (unsigned int y = 0; y < unsigned(h); y++)
230 		{
231 			int p = (y*unsigned(w)*4) + (x*4) + 3;
232 			if (p < size && data[p] >= 254)
233 			{
234 				if (smallesty == -1 || y < smallesty)
235 					smallesty = y;
236 				if (largesty == -1 || y > largesty)
237 					largesty = y;
238 			}
239 		}
240 	}
241 	free(data);
242 	return largesty - smallesty;
243 #elif defined(BBGE_BUILD_DIRECTX)
244 	return 0;
245 #endif
246 }
247 
reload()248 void Texture::reload()
249 {
250 	debugLog("RELOADING TEXTURE: " + name + " with loadName " + loadName + "...");
251 
252 	unload();
253 	load(loadName);
254 
255 	/*if (ow != -1 && oh != -1)
256 	{
257 		width = ow;
258 		height = oh;
259 	}*/
260 	debugLog("DONE");
261 }
262 
load(std::string file)263 bool Texture::load(std::string file)
264 {
265 	if (file.size()<4)
266 	{
267 		errorLog("Texture Name is Empty or Too Short");
268 		return false;
269 	}
270 
271 	stringToLowerUserData(file);
272 	file = core->adjustFilenameCase(file);
273 
274 	loadName = file;
275 	repeating = false;
276 
277 	size_t pos = file.find_last_of('.');
278 
279 	if ((pos != std::string::npos) && (pos >= 0))
280 	{
281 		// make sure this didn't catch the '.' in /home/username/.Aquaria/*  --ryan.
282 		const std::string userdata = core->getUserDataFolder();
283 		const size_t len = userdata.length();
284 		if (pos < len)
285 			pos = std::string::npos;
286 	}
287 
288 	/*if (core->debugLogTextures)
289 	{
290 		std::ostringstream os;
291 		os << "pos [" << pos << "], file :" << file;
292 		debugLog(os.str());
293 	}*/
294 
295 	bool found = exists(file);
296 
297 	if(!found && exists(file + ".png"))
298 	{
299 		found = true;
300 		file += ".png";
301 	}
302 
303 	// .tga/.zga are never used as game graphics anywhere except save slot thumbnails.
304 	// if so, their file names are passed exact, not with a missing extension
305 
306 	if (found)
307 	{
308 		file = localisePathInternalModpath(file);
309 		file = core->adjustFilenameCase(file);
310 
311 		/*
312 		std::ostringstream os;
313 		os << "Loading texture [" << file << "]";
314 		debugLog(os.str());
315 		*/
316 		std::string post = file.substr(file.size()-3, 3);
317 		stringToLower(post);
318 		if (post == "png")
319 		{
320 
321 #ifdef BBGE_BUILD_OPENGL
322 			return loadPNG(file);
323 #endif
324 
325 #ifdef BBGE_BUILD_DIRECTX
326 			D3DXCreateTextureFromFile(core->getD3DDevice(),  file.c_str(),	&this->d3dTexture);
327 			if (!d3dTexture)
328 			{
329 				errorLog ("failed to load texture");
330 			}
331 			else
332 			{
333 				D3DSURFACE_DESC desc;
334 				this->d3dTexture->GetLevelDesc(0,&desc);
335 
336 				width = desc.Width;
337 				height = desc.Height;
338 			}
339 #endif
340 		}
341 		else if (post == "zga")
342 		{
343 			return loadZGA(file);
344 		}
345 		else if (post == "tga")
346 		{
347 			return loadTGA(file);
348 		}
349 		else
350 		{
351 			debugLog("unknown image file type: " + file);
352 		}
353 	}
354 	else
355 	{
356 		// load default image / leave white
357 		if (core->debugLogTextures)
358 			debugLog("***Could not find texture: " + file);
359 	}
360 	return false;
361 }
362 
apply(bool repeatOverride)363 void Texture::apply(bool repeatOverride)
364 {
365 #ifdef BBGE_BUILD_OPENGL
366 	glBindTexture(GL_TEXTURE_2D, textures[0]);
367 	if (repeat || repeatOverride)
368 	{
369 		if (!repeating)
370 		{
371 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
372 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
373 			repeating = true;
374 		}
375 	}
376 	else
377 	{
378 		if (repeating)
379 		{
380 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
381 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
382 			repeating = false;
383 		}
384 	}
385 #endif
386 #ifdef BBGE_BUILD_DIRECTX
387 	core->getD3DDevice()->SetTexture(0, d3dTexture);
388 
389 #endif
390 }
391 
unbind()392 void Texture::unbind()
393 {
394 }
395 
loadPNG(const std::string & file)396 bool Texture::loadPNG(const std::string &file)
397 {
398 	if (file.empty()) return false;
399 	bool good = false;
400 
401 #ifdef BBGE_BUILD_OPENGL
402 
403 
404 	pngInfo info;
405 
406 	int pngType = PNG_ALPHA;
407 
408 	if (format != 0)
409 	{
410 		if (format == GL_LUMINANCE_ALPHA)
411 			pngType = PNG_LUMINANCEALPHA;
412 	}
413 
414 	unsigned long memsize = 0;
415 	const char *memptr = readFile(file, &memsize);
416 	if(!memptr || !memsize)
417 		goto fail;
418 
419 	if (filter == GL_NEAREST)
420 	{
421 		textures[0] = pngBindMem(memptr, memsize, PNG_NOMIPMAPS, pngType, &info, GL_CLAMP_TO_EDGE, filter, filter);
422 	}
423 	else
424 	{
425 		textures[0] = pngBindMem(memptr, memsize, PNG_BUILDMIPMAPS, pngType, &info, GL_CLAMP_TO_EDGE, GL_LINEAR_MIPMAP_LINEAR, filter);
426 	}
427 
428 	if (textures[0] != 0)
429 	{
430 		width = info.Width;
431 		height = info.Height;
432 		good = true;
433 	}
434 	else
435 	{
436 		fail:
437 
438 		debugLog("Can't load PNG file: " + file);
439 	}
440 
441 	if(memptr)
442 		delete [] memptr;
443 
444 #endif
445 	return good;
446 }
447 
448 // internal load functions
loadTGA(const std::string & file)449 bool Texture::loadTGA(const std::string &file)
450 {
451 	return loadTGA(TGAload(file.c_str()));
452 }
453 
loadZGA(const std::string & file)454 bool Texture::loadZGA(const std::string &file)
455 {
456 	unsigned long size = 0;
457 	char *buf = readCompressedFile(file, &size);
458 	ImageTGA *tga = TGAloadMem(buf, size);
459 	if (!tga)
460 	{
461 		debugLog("Can't load ZGA File: " + file);
462 		return false;
463 	}
464 	return loadTGA(tga);
465 }
466 
loadTGA(ImageTGA * imageTGA)467 bool Texture::loadTGA(ImageTGA *imageTGA)
468 {
469 	if (!imageTGA)
470 		return false;
471 
472 	glGenTextures(1, &textures[0]);
473 	glBindTexture(GL_TEXTURE_2D, textures[0]);
474 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,filter);	// Linear Filtering
475 	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,filter);	// Linear Filtering
476 
477 	if (imageTGA->channels==3)
478 		glTexImage2D(GL_TEXTURE_2D, 0, 3, imageTGA->sizeX, imageTGA->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, imageTGA->data);
479 	else if (imageTGA->channels==4)
480 		glTexImage2D(GL_TEXTURE_2D, 0, 4,imageTGA->sizeX, imageTGA->sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageTGA->data);
481 
482 	width = imageTGA->sizeX;
483 	height = imageTGA->sizeY;
484 
485 	if (imageTGA->data)
486 		delete[] (imageTGA->data);
487 	free (imageTGA);
488 
489 	return true;
490 }
491 
492 
493 #define TGA_RGB		 2		// This tells us it's a normal RGB (really BGR) file
494 #define TGA_A		 3		// This tells us it's a ALPHA file
495 #define TGA_RLE		10		// This tells us that the targa is Run-Length Encoded (RLE)
496 
497 #if defined(BBGE_BUILD_UNIX)
498 typedef uint8_t byte;
499 typedef uint16_t WORD;
500 #endif
501 
502 
503 #ifdef BBGE_BUILD_WINDOWS
504 	#define byte char
505 #endif
506 
TGAload(const char * filename)507 ImageTGA *Texture::TGAload(const char *filename)
508 {
509 	unsigned long size = 0;
510 	char *rawbuf = readFile(filename, &size);
511 	ImageTGA *tga = TGAloadMem(rawbuf, size);
512 	if (rawbuf)
513 		delete [] rawbuf;
514 	if (!tga)
515 	{
516 		debugLog("Can't load TGA File!");
517 		return NULL;
518 	}
519 	return tga;
520 }
521 
TGAloadMem(void * mem,int size)522 ImageTGA *Texture::TGAloadMem(void *mem, int size)
523 {
524 	if (!mem || size < 20)
525 		return NULL;
526 
527 	ByteBuffer bb(mem, size, ByteBuffer::REUSE);
528 
529 	ImageTGA *pImageData = NULL;		// This stores our important image data
530 	WORD width = 0, height = 0;			// The dimensions of the image
531 	byte length = 0;					// The length in bytes to the pixels
532 	byte imageType = 0;					// The image type (RLE, RGB, Alpha...)
533 	byte bits = 0;						// The bits per pixel for the image (16, 24, 32)
534 	int channels = 0;					// The channels of the image (3 = RGA : 4 = RGBA)
535 	int stride = 0;						// The stride (channels * width)
536 	int i = 0;							// A counter
537 
538 	// This function loads in a TARGA (.TGA) file and returns its data to be
539 	// used as a texture or what have you.  This currently loads in a 16, 24
540 	// and 32-bit targa file, along with RLE compressed files.  Eventually you
541 	// will want to do more error checking to make it more robust.  This is
542 	// also a perfect start to go into a modular class for an engine.
543 	// Basically, how it works is, you read in the header information, then
544 	// move your file pointer to the pixel data.  Before reading in the pixel
545 	// data, we check to see the if it's an RLE compressed image.  This is because
546 	// we will handle it different.  If it isn't compressed, then we need another
547 	// check to see if we need to convert it from 16-bit to 24 bit.  24-bit and
548 	// 32-bit textures are very similar, so there's no need to do anything special.
549 	// We do, however, read in an extra bit for each color.
550 
551 
552 	// Allocate the structure that will hold our eventual image data (must free it!)
553 	pImageData = (ImageTGA*)malloc(sizeof(ImageTGA));
554 
555 	// Read in the length in bytes from the header to the pixel data
556 	bb >> length;
557 
558 	// Jump over one byte
559 	bb.skipRead(1);
560 
561 	// Read in the imageType (RLE, RGB, etc...)
562 	//fread(&imageType, sizeof(byte), 1, pFile);
563 	bb >> imageType;
564 
565 	// Skip past general information we don't care about
566 	bb.skipRead(9);
567 
568 	// Read the width, height and bits per pixel (16, 24 or 32)
569 	bb >> width >> height >> bits;
570 
571 	/*
572 	std::ostringstream os;
573 	os << "TGALoad: width: " << width << " height: " << height << " bits: " << bits;
574 	debugLog(os.str());
575 	*/
576 
577 	// Now we move the file pointer to the pixel data
578 	bb.skipRead(length + 1);
579 
580 	// Check if the image is RLE compressed or not
581 	if(imageType != TGA_RLE)
582 	{
583 		// Check if the image is a 24 or 32-bit image
584 		if(bits == 24 || bits == 32)
585 		{
586 			// Calculate the channels (3 or 4) - (use bits >> 3 for more speed).
587 			// Next, we calculate the stride and allocate enough memory for the pixels.
588 			channels = bits / 8;
589 			stride = channels * width;
590 			pImageData->data = new unsigned char[stride * height];
591 
592 			// Load in all the pixel data line by line
593 			for(int y = 0; y < height; y++)
594 			{
595 				// Store a pointer to the current line of pixels
596 				unsigned char *pLine = &(pImageData->data[stride * y]);
597 
598 				// Read in the current line of pixels
599 				if (bb.readable() < stride)
600 					break;
601 				bb.read(pLine, stride);
602 
603 				// Go through all of the pixels and swap the B and R values since TGA
604 				// files are stored as BGR instead of RGB (or use GL_BGR_EXT verses GL_RGB)
605 				for(i = 0; i < stride; i += channels)
606 				{
607 					int temp     = pLine[i];
608 					pLine[i]     = pLine[i + 2];
609 					pLine[i + 2] = temp;
610 				}
611 			}
612 		}
613 		// Check if the image is a 16 bit image (RGB stored in 1 unsigned short)
614 		else if(bits == 16)
615 		{
616 			unsigned short pixels = 0;
617 			int r=0, g=0, b=0;
618 
619 			// Since we convert 16-bit images to 24 bit, we hardcode the channels to 3.
620 			// We then calculate the stride and allocate memory for the pixels.
621 			channels = 3;
622 			stride = channels * width;
623 			pImageData->data = new unsigned char[stride * height];
624 
625 			// Load in all the pixel data pixel by pixel
626 			for(int i = 0; i < width*height; i++)
627 			{
628 				// Read in the current pixel
629 				if (bb.readable() < sizeof(unsigned char))
630 					break;
631 				bb >> pixels;
632 
633 				// To convert a 16-bit pixel into an R, G, B, we need to
634 				// do some masking and such to isolate each color value.
635 				// 0x1f = 11111 in binary, so since 5 bits are reserved in
636 				// each unsigned short for the R, G and B, we bit shift and mask
637 				// to find each value.  We then bit shift up by 3 to get the full color.
638 				b = (pixels & 0x1f) << 3;
639 				g = ((pixels >> 5) & 0x1f) << 3;
640 				r = ((pixels >> 10) & 0x1f) << 3;
641 
642 				// This essentially assigns the color to our array and swaps the
643 				// B and R values at the same time.
644 				pImageData->data[i * 3 + 0] = r;
645 				pImageData->data[i * 3 + 1] = g;
646 				pImageData->data[i * 3 + 2] = b;
647 			}
648 		}
649 		// Else return a NULL for a bad or unsupported pixel format
650 		else
651 			return NULL;
652 	}
653 	// Else, it must be Run-Length Encoded (RLE)
654 	else
655 	{
656 		// First, let me explain real quickly what RLE is.
657 		// For further information, check out Paul Bourke's intro article at:
658 		// http://astronomy.swin.edu.au/~pbourke/dataformats/rle/
659 		//
660 		// Anyway, we know that RLE is a basic type compression.  It takes
661 		// colors that are next to each other and then shrinks that info down
662 		// into the color and a integer that tells how much of that color is used.
663 		// For instance:
664 		// aaaaabbcccccccc would turn into a5b2c8
665 		// Well, that's fine and dandy and all, but how is it down with RGB colors?
666 		// Simple, you read in an color count (rleID), and if that number is less than 128,
667 		// it does NOT have any optimization for those colors, so we just read the next
668 		// pixels normally.  Say, the color count was 28, we read in 28 colors like normal.
669 		// If the color count is over 128, that means that the next color is optimized and
670 		// we want to read in the same pixel color for a count of (colorCount - 127).
671 		// It's 127 because we add 1 to the color count, as you'll notice in the code.
672 
673 		// Create some variables to hold the rleID, current colors read, channels, & stride.
674 		byte rleID = 0;
675 		int colorsRead = 0;
676 		channels = bits / 8;
677 		stride = channels * width;
678 
679 		// Next we want to allocate the memory for the pixels and create an array,
680 		// depending on the channel count, to read in for each pixel.
681 		pImageData->data = new unsigned char[stride * height];
682 		byte *pColors = new byte [channels];
683 
684 		// Load in all the pixel data
685 		while(i < width*height)
686 		{
687 			// Read in the current color count + 1
688 			bb >> rleID;
689 
690 			// Check if we don't have an encoded string of colors
691 			if(rleID < 128)
692 			{
693 				// Increase the count by 1
694 				rleID++;
695 
696 				// Go through and read all the unique colors found
697 				while(rleID)
698 				{
699 					// Read in the current color
700 					if (bb.readable() < channels)
701 						break;
702 					bb.read(pColors, channels);
703 
704 					// Store the current pixel in our image array
705 					pImageData->data[colorsRead + 0] = pColors[2];
706 					pImageData->data[colorsRead + 1] = pColors[1];
707 					pImageData->data[colorsRead + 2] = pColors[0];
708 
709 					// If we have a 4 channel 32-bit image, assign one more for the alpha
710 					if(bits == 32)
711 						pImageData->data[colorsRead + 3] = pColors[3];
712 
713 					// Increase the current pixels read, decrease the amount
714 					// of pixels left, and increase the starting index for the next pixel.
715 					i++;
716 					rleID--;
717 					colorsRead += channels;
718 				}
719 			}
720 			// Else, let's read in a string of the same character
721 			else
722 			{
723 				// Minus the 128 ID + 1 (127) to get the color count that needs to be read
724 				rleID -= 127;
725 
726 				// Read in the current color, which is the same for a while
727 				if (bb.readable() < channels)
728 					break;
729 				bb.read(pColors, channels);
730 
731 				// Go and read as many pixels as are the same
732 				while(rleID)
733 				{
734 					// Assign the current pixel to the current index in our pixel array
735 					pImageData->data[colorsRead + 0] = pColors[2];
736 					pImageData->data[colorsRead + 1] = pColors[1];
737 					pImageData->data[colorsRead + 2] = pColors[0];
738 
739 					// If we have a 4 channel 32-bit image, assign one more for the alpha
740 					if(bits == 32)
741 						pImageData->data[colorsRead + 3] = pColors[3];
742 
743 					// Increase the current pixels read, decrease the amount
744 					// of pixels left, and increase the starting index for the next pixel.
745 					i++;
746 					rleID--;
747 					colorsRead += channels;
748 				}
749 
750 			}
751 
752 		}
753 
754 		// Free up pColors
755 		delete[] pColors;
756 	}
757 
758 	// Fill in our tImageTGA structure to pass back
759 	pImageData->channels = channels;
760 	pImageData->sizeX    = width;
761 	pImageData->sizeY    = height;
762 
763 	// Return the TGA data (remember, you must free this data after you are done)
764 	return pImageData;
765 }
766 
767 // ceil to next power of 2
clp2(unsigned int x)768 static unsigned int clp2(unsigned int x)
769 {
770 	--x;
771 	x |= (x >> 1);
772 	x |= (x >> 2);
773 	x |= (x >> 4);
774 	x |= (x >> 8);
775 	x |= (x >> 16);
776 	return x + 1;
777 }
778 
getBufferAndSize(int * wparam,int * hparam,unsigned int * sizeparam)779 unsigned char * Texture::getBufferAndSize(int *wparam, int *hparam, unsigned int *sizeparam)
780 {
781 	unsigned char *data = NULL;
782 	unsigned int size = 0;
783 	int tw = 0, th = 0;
784 	int w = 0, h = 0;
785 
786 	// This can't happen. If it does we're doomed.
787 	if(width <= 0 || height <= 0)
788 		goto fail;
789 
790 	glBindTexture(GL_TEXTURE_2D, textures[0]);
791 
792 	// As returned by graphics driver
793 
794 	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
795 	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
796 
797 	// As we know it - but round to nearest power of 2 - OpenGL does this internally anyways.
798 	tw = clp2(width); // known to be > 0.
799 	th = clp2(height);
800 
801 	if (w != tw || h != th)
802 	{
803 		std::ostringstream os;
804 		os << "Texture::getBufferAndSize() WARNING: width/height disagree: ";
805 		os << "Driver says (" << w << ", " << h << "); ";
806 		os << "Texture says (" << width << ", " << height << "); ";
807 		os << "Rounded to (" << tw << ", " << th << ")";
808 		debugLog(os.str());
809 		// choose max. for size calculation
810 		w = w > tw ? w : tw;
811 		h = h > th ? h : th;
812 	}
813 
814 	size = w * h * 4;
815 	if (!size)
816 		goto fail;
817 
818 	data = (unsigned char*)malloc(size + 32);
819 	if (!data)
820 	{
821 		std::ostringstream os;
822 		os << "Game::fillGridFromQuad allocation failure, size = " << size;
823 		errorLog(os.str());
824 		goto fail;
825 	}
826 	memcpy(data + size, "SAFE", 5);
827 	glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
828 	glBindTexture(GL_TEXTURE_2D, 0);
829 
830 	// Not sure but this might be the case with nouveau drivers on linux... still investigating. -- fg
831 	if(memcmp(data + size, "SAFE", 5))
832 	{
833 		errorLog("Texture::getBufferAndSize(): Broken graphics driver! Wrote past end of buffer!");
834 		free(data); // in case we are here, this will most likely cause a crash.
835 		goto fail;
836 	}
837 
838 	*wparam = w;
839 	*hparam = h;
840 	*sizeparam = size;
841 	return data;
842 
843 
844 fail:
845 	*wparam = 0;
846 	*hparam = 0;
847 	*sizeparam = 0;
848 	return NULL;
849 }
850