hostsupport/hostopengles11/src/GLESTexture.cpp
branchbug235_bringup_0
changeset 53 c2ef9095503a
child 68 8d4efe9fa1cf
equal deleted inserted replaced
52:39e5f73667ba 53:c2ef9095503a
       
     1 /* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     2  *
       
     3  * Permission is hereby granted, free of charge, to any person obtaining a
       
     4  * copy of this software and /or associated documentation files
       
     5  * (the "Materials "), to deal in the Materials without restriction,
       
     6  * including without limitation the rights to use, copy, modify, merge,
       
     7  * publish, distribute, sublicense, and/or sell copies of the Materials,
       
     8  * and to permit persons to whom the Materials are furnished to do so,
       
     9  * subject to the following conditions:
       
    10  *
       
    11  * The above copyright notice and this permission notice shall be included
       
    12  * in all copies or substantial portions of the Materials.
       
    13  *
       
    14  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
       
    15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
       
    16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
       
    17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
       
    18  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
       
    19  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
       
    20  * THE USE OR OTHER DEALINGS IN THE MATERIALS.
       
    21  *
       
    22  * Initial Contributors:
       
    23  * Nokia Corporation - initial contribution.
       
    24  *
       
    25  * Contributors:
       
    26  *
       
    27  * Description:
       
    28  *
       
    29  */
       
    30 
       
    31 #include "GLESTexture.h"
       
    32 #include "glesInternal.h"
       
    33 
       
    34 GLESTexture::GLESTexture(unsigned int name) :
       
    35 	m_name(name),
       
    36 	m_numLevels(0),
       
    37 	m_levels(NULL)
       
    38 {
       
    39 }
       
    40 
       
    41 GLESTexture::~GLESTexture()
       
    42 {
       
    43 	delete[] m_levels;
       
    44 }
       
    45 
       
    46 bool GLESTexture::AllocateLevels(int numLevels)
       
    47 {
       
    48 	GLES_ASSERT(m_levels == NULL);
       
    49 
       
    50 	m_numLevels = numLevels;
       
    51 	m_levels = GLES_NEW GLESTextureLevel[numLevels];
       
    52 	if(m_levels == NULL)
       
    53 	{
       
    54 		return false;
       
    55 	}
       
    56 
       
    57 	for(int i = 0; i < numLevels; i++)
       
    58 	{
       
    59 		// From desktop GL spec.
       
    60 		m_levels[i].format = 1;
       
    61 		m_levels[i].width = 0;
       
    62 		m_levels[i].height = 0;
       
    63 		
       
    64 		m_levels[i].boundSurface = NULL;
       
    65 	}
       
    66 
       
    67 	return true;
       
    68 }
       
    69 
       
    70 GLESTextureLevel* GLESTexture::Level(int level)
       
    71 {
       
    72 	GLES_ASSERT(m_levels != NULL);
       
    73 	GLES_ASSERT(level >= 0 && level < m_numLevels);
       
    74 	return &m_levels[level];
       
    75 }
       
    76 
       
    77 void GLESTexture::SetLevel(int level, GLenum format, GLsizei width, GLsizei height)
       
    78 {
       
    79 	GLES_ASSERT(m_levels != NULL);
       
    80 	GLES_ASSERT(level >= 0 && level < m_numLevels);
       
    81 	m_levels[level].format = format;
       
    82 	m_levels[level].width = width;
       
    83 	m_levels[level].height = height;
       
    84 }
       
    85 
       
    86 void GLESTexture::GenerateMipmap()
       
    87 {
       
    88 	GLES_ASSERT(m_levels != NULL);
       
    89 
       
    90 	const GLESTextureLevel& level_zero = m_levels[0];
       
    91 
       
    92 	m_numLevels = glesLog2(GLES_MAX(level_zero.width, level_zero.height)) + 1;
       
    93 
       
    94 	int width = level_zero.width;
       
    95 	int height = level_zero.height;
       
    96 
       
    97 	for(int level = 1; level < m_numLevels; level++)
       
    98 	{
       
    99 		if(width > 1) width /= 2;
       
   100 		if(height > 1) height /= 2;
       
   101 
       
   102 		GLES_ASSERT((width > 1 || height > 1) || level == m_numLevels - 1);
       
   103 
       
   104 		m_levels[level].format = level_zero.format;
       
   105 		m_levels[level].width = width;
       
   106 		m_levels[level].height = height;
       
   107 	}
       
   108 }
       
   109 
       
   110 bool glesIsValidCompressedFormat(GLenum format)
       
   111 {
       
   112 	switch(format)
       
   113 	{
       
   114 	case GL_PALETTE4_RGB8_OES:
       
   115 	case GL_PALETTE4_RGBA8_OES:
       
   116 	case GL_PALETTE4_R5_G6_B5_OES:
       
   117 	case GL_PALETTE4_RGBA4_OES:
       
   118 	case GL_PALETTE4_RGB5_A1_OES:
       
   119 	case GL_PALETTE8_RGB8_OES:
       
   120 	case GL_PALETTE8_RGBA8_OES:
       
   121 	case GL_PALETTE8_R5_G6_B5_OES:
       
   122 	case GL_PALETTE8_RGBA4_OES:
       
   123 	case GL_PALETTE8_RGB5_A1_OES:
       
   124 		return true;
       
   125 	default:
       
   126 		return false;
       
   127 	}
       
   128 }
       
   129 
       
   130 GLenum glesMapCompressedToBaseFormat(GLenum format)
       
   131 {
       
   132 	switch(format)
       
   133 	{
       
   134 	case GL_PALETTE4_RGB8_OES:
       
   135 	case GL_PALETTE4_R5_G6_B5_OES:
       
   136 	case GL_PALETTE8_RGB8_OES:
       
   137 	case GL_PALETTE8_R5_G6_B5_OES:
       
   138 		return GL_RGB;
       
   139 
       
   140 	case GL_PALETTE4_RGBA8_OES:
       
   141 	case GL_PALETTE4_RGBA4_OES:
       
   142 	case GL_PALETTE4_RGB5_A1_OES:
       
   143 	case GL_PALETTE8_RGBA8_OES:
       
   144 	case GL_PALETTE8_RGBA4_OES:
       
   145 	case GL_PALETTE8_RGB5_A1_OES:
       
   146 		return GL_RGBA;
       
   147 	
       
   148 	default:
       
   149 		GLES_ASSERT(false);
       
   150 	}
       
   151 
       
   152 	// not reached
       
   153 	return 0;
       
   154 }
       
   155 
       
   156 void* glesUncompressImage(int level, GLenum format, int width, int height, int imageSize, const void* data)
       
   157 {
       
   158 	const unsigned char* palette = static_cast<const unsigned char*>(data);
       
   159 	int bitsPerPixel;
       
   160 	int paletteEntrySize;
       
   161 	
       
   162 	switch(format)
       
   163 	{
       
   164 	case GL_PALETTE4_RGB8_OES:
       
   165 		bitsPerPixel = 4;
       
   166 		paletteEntrySize = 3;
       
   167 		break;
       
   168 
       
   169 	case GL_PALETTE4_RGBA8_OES:
       
   170 		bitsPerPixel = 4;
       
   171 		paletteEntrySize = 4;
       
   172 		break;
       
   173 
       
   174 	case GL_PALETTE4_R5_G6_B5_OES:
       
   175 	case GL_PALETTE4_RGB5_A1_OES:
       
   176 	case GL_PALETTE4_RGBA4_OES:
       
   177 		bitsPerPixel = 4;
       
   178 		paletteEntrySize = 2;
       
   179 		break;
       
   180 
       
   181 	case GL_PALETTE8_RGB8_OES:
       
   182 		bitsPerPixel = 8;
       
   183 		paletteEntrySize = 3;
       
   184 		break;
       
   185 
       
   186 	case GL_PALETTE8_RGBA8_OES:
       
   187 		bitsPerPixel = 8;
       
   188 		paletteEntrySize = 4;
       
   189 		break;
       
   190 
       
   191 	case GL_PALETTE8_R5_G6_B5_OES:
       
   192 	case GL_PALETTE8_RGBA4_OES:
       
   193 	case GL_PALETTE8_RGB5_A1_OES:
       
   194 		bitsPerPixel = 8;
       
   195 		paletteEntrySize = 2;
       
   196 		break;
       
   197 
       
   198 	default:
       
   199 		GLES_ASSERT(false);
       
   200 	}
       
   201 
       
   202 	int numPaletteEntries = 2 << (bitsPerPixel - 1);
       
   203 	const unsigned char* imageData = palette + numPaletteEntries * paletteEntrySize;
       
   204 
       
   205 	// Skip to the correct mip level
       
   206 	for(int i = 0; i < level; i++)
       
   207 	{
       
   208 		if(bitsPerPixel == 8)
       
   209 		{
       
   210 			imageData += width * height * bitsPerPixel / 8;
       
   211 		}
       
   212 		else
       
   213 		{
       
   214 			GLES_ASSERT(bitsPerPixel == 4);
       
   215 			imageData += width * height * bitsPerPixel / 8 / 2;
       
   216 		}
       
   217 		width /= 2;
       
   218 		height /= 2;
       
   219 	}
       
   220 
       
   221 	int bytesPerPixel;
       
   222 	GLenum baseFormat = glesMapCompressedToBaseFormat(format);
       
   223 	if(baseFormat == GL_RGB)
       
   224 	{
       
   225 		bytesPerPixel = 3;
       
   226 	}
       
   227 	else
       
   228 	{
       
   229 		GLES_ASSERT(baseFormat == GL_RGBA);
       
   230 		bytesPerPixel = 4;
       
   231 	}
       
   232 
       
   233 	char* uncompressedData = GLES_NEW char[width * height * bytesPerPixel];
       
   234 	if(uncompressedData == NULL)
       
   235 	{
       
   236 		return NULL;
       
   237 	}
       
   238 	
       
   239 	// Don't go past the end of the data
       
   240 	int pixelsPerByte = 8 / bitsPerPixel;
       
   241 	int maxPixels = (static_cast<const unsigned char*>(data) + imageSize - imageData) * pixelsPerByte;
       
   242 	int end = GLES_MIN(width * height, maxPixels);
       
   243 
       
   244 	for(int i = 0; i < end; i++)
       
   245 	{
       
   246 		int index;
       
   247 		if(bitsPerPixel == 4)
       
   248 		{
       
   249 			if(i & 1)
       
   250 			{
       
   251 				index = imageData[i / 2] & 15;
       
   252 			}
       
   253 			else
       
   254 			{
       
   255 				index = imageData[i / 2] >> 4;
       
   256 			}
       
   257 		}
       
   258 		else
       
   259 		{
       
   260 			GLES_ASSERT(bitsPerPixel == 8);
       
   261 			index = imageData[i];
       
   262 		}
       
   263 
       
   264 		int r, g, b, a;
       
   265 
       
   266 		switch(format)
       
   267 		{
       
   268 		case GL_PALETTE4_RGB8_OES:
       
   269 		case GL_PALETTE8_RGB8_OES:
       
   270 			r = palette[index*3];
       
   271 			g = palette[index*3+1];
       
   272 			b = palette[index*3+2];
       
   273 			break;
       
   274 
       
   275 		case GL_PALETTE4_RGBA8_OES:
       
   276 		case GL_PALETTE8_RGBA8_OES:
       
   277 			r = palette[index*4];
       
   278 			g = palette[index*4+1];
       
   279 			b = palette[index*4+2];
       
   280 			a = palette[index*4+3];
       
   281 			break;
       
   282 
       
   283 		case GL_PALETTE4_R5_G6_B5_OES:
       
   284 		case GL_PALETTE8_R5_G6_B5_OES:
       
   285 			r = palette[index*2+1] >> 3;
       
   286 			r = (r << 3) | (r >> 2);
       
   287 			g = ((palette[index*2+1] & 7) << 3) | (palette[index*2] >> 5);
       
   288 			g = (g << 2) | (g >> 4);
       
   289 			b = palette[index*2] & 0x1f;
       
   290 			b = (b << 3) | (b >> 2);
       
   291 			break;
       
   292 
       
   293 		case GL_PALETTE4_RGBA4_OES:
       
   294 		case GL_PALETTE8_RGBA4_OES:
       
   295 			r = palette[index*2+1] >> 4;
       
   296 			r |= (r << 4) | r;
       
   297 			g = palette[index*2+1] & 0xf;
       
   298 			g |= (g << 4) | g;
       
   299 			b = palette[index*2] >> 4;
       
   300 			b |= (b << 4) | b;
       
   301 			a = palette[index*2] & 0xf;
       
   302 			a |= (a << 4) | a;
       
   303 			break;
       
   304 
       
   305 		case GL_PALETTE4_RGB5_A1_OES:
       
   306 		case GL_PALETTE8_RGB5_A1_OES:
       
   307 			r = palette[index*2+1] >> 3;
       
   308 			r = (r << 3) | (r >> 2);
       
   309 			g = ((palette[index*2+1] & 7) << 2) | (palette[index*2] >> 6);
       
   310 			g = (g << 3) | (g >> 2);
       
   311 			b = (palette[index*2] >> 1) & 0x1f;
       
   312 			b = (b << 3) | (b >> 2);
       
   313 			a = (palette[index*2] & 1) ? 255 : 0;
       
   314 			break;
       
   315 			
       
   316 		default:
       
   317 			GLES_ASSERT(false);
       
   318 		}
       
   319 
       
   320 		if(baseFormat == GL_RGB)
       
   321 		{
       
   322 			uncompressedData[i*3+0] = r;
       
   323 			uncompressedData[i*3+1] = g;
       
   324 			uncompressedData[i*3+2] = b;
       
   325 		}
       
   326 		else
       
   327 		{
       
   328 			GLES_ASSERT(baseFormat == GL_RGBA);
       
   329 			uncompressedData[i*4+0] = r;
       
   330 			uncompressedData[i*4+1] = g;
       
   331 			uncompressedData[i*4+2] = b;
       
   332 			uncompressedData[i*4+3] = a;
       
   333 		}
       
   334 	}
       
   335 
       
   336 	return uncompressedData;
       
   337 }