1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Mesa 3-D graphics library 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Copyright 2008 VMware, Inc. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 14bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci/** 26bf215546Sopenharmony_ci * Code to convert compressed/paletted texture images to ordinary images. 27bf215546Sopenharmony_ci * See the GL_OES_compressed_paletted_texture spec at 28bf215546Sopenharmony_ci * http://khronos.org/registry/gles/extensions/OES/OES_compressed_paletted_texture.txt 29bf215546Sopenharmony_ci * 30bf215546Sopenharmony_ci * XXX this makes it impossible to add hardware support... 31bf215546Sopenharmony_ci */ 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "glheader.h" 35bf215546Sopenharmony_ci#include "context.h" 36bf215546Sopenharmony_ci#include "mtypes.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#include "pixelstore.h" 39bf215546Sopenharmony_ci#include "texcompress_cpal.h" 40bf215546Sopenharmony_ci#include "teximage.h" 41bf215546Sopenharmony_ci#include "api_exec_decl.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_cistatic const struct cpal_format_info { 45bf215546Sopenharmony_ci GLenum cpal_format; 46bf215546Sopenharmony_ci GLenum format; 47bf215546Sopenharmony_ci GLenum type; 48bf215546Sopenharmony_ci GLuint palette_size; 49bf215546Sopenharmony_ci GLuint size; 50bf215546Sopenharmony_ci} formats[] = { 51bf215546Sopenharmony_ci { GL_PALETTE4_RGB8_OES, GL_RGB, GL_UNSIGNED_BYTE, 16, 3 }, 52bf215546Sopenharmony_ci { GL_PALETTE4_RGBA8_OES, GL_RGBA, GL_UNSIGNED_BYTE, 16, 4 }, 53bf215546Sopenharmony_ci { GL_PALETTE4_R5_G6_B5_OES, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16, 2 }, 54bf215546Sopenharmony_ci { GL_PALETTE4_RGBA4_OES, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16, 2 }, 55bf215546Sopenharmony_ci { GL_PALETTE4_RGB5_A1_OES, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16, 2 }, 56bf215546Sopenharmony_ci { GL_PALETTE8_RGB8_OES, GL_RGB, GL_UNSIGNED_BYTE, 256, 3 }, 57bf215546Sopenharmony_ci { GL_PALETTE8_RGBA8_OES, GL_RGBA, GL_UNSIGNED_BYTE, 256, 4 }, 58bf215546Sopenharmony_ci { GL_PALETTE8_R5_G6_B5_OES, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 256, 2 }, 59bf215546Sopenharmony_ci { GL_PALETTE8_RGBA4_OES, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 256, 2 }, 60bf215546Sopenharmony_ci { GL_PALETTE8_RGB5_A1_OES, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 256, 2 } 61bf215546Sopenharmony_ci}; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci/** 65bf215546Sopenharmony_ci * Get a color/entry from the palette. 66bf215546Sopenharmony_ci */ 67bf215546Sopenharmony_cistatic GLuint 68bf215546Sopenharmony_ciget_palette_entry(const struct cpal_format_info *info, const GLubyte *palette, 69bf215546Sopenharmony_ci GLuint index, GLubyte *pixel) 70bf215546Sopenharmony_ci{ 71bf215546Sopenharmony_ci memcpy(pixel, palette + info->size * index, info->size); 72bf215546Sopenharmony_ci return info->size; 73bf215546Sopenharmony_ci} 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci/** 77bf215546Sopenharmony_ci * Convert paletted texture to color texture. 78bf215546Sopenharmony_ci */ 79bf215546Sopenharmony_cistatic void 80bf215546Sopenharmony_cipaletted_to_color(const struct cpal_format_info *info, const GLubyte *palette, 81bf215546Sopenharmony_ci const void *indices, GLuint num_pixels, GLubyte *image) 82bf215546Sopenharmony_ci{ 83bf215546Sopenharmony_ci GLubyte *pix = image; 84bf215546Sopenharmony_ci GLuint remain, i; 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci if (info->palette_size == 16) { 87bf215546Sopenharmony_ci /* 4 bits per index */ 88bf215546Sopenharmony_ci const GLubyte *ind = (const GLubyte *) indices; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci /* two pixels per iteration */ 91bf215546Sopenharmony_ci remain = num_pixels % 2; 92bf215546Sopenharmony_ci for (i = 0; i < num_pixels / 2; i++) { 93bf215546Sopenharmony_ci pix += get_palette_entry(info, palette, (ind[i] >> 4) & 0xf, pix); 94bf215546Sopenharmony_ci pix += get_palette_entry(info, palette, ind[i] & 0xf, pix); 95bf215546Sopenharmony_ci } 96bf215546Sopenharmony_ci if (remain) { 97bf215546Sopenharmony_ci get_palette_entry(info, palette, (ind[i] >> 4) & 0xf, pix); 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci else { 101bf215546Sopenharmony_ci /* 8 bits per index */ 102bf215546Sopenharmony_ci const GLubyte *ind = (const GLubyte *) indices; 103bf215546Sopenharmony_ci for (i = 0; i < num_pixels; i++) 104bf215546Sopenharmony_ci pix += get_palette_entry(info, palette, ind[i], pix); 105bf215546Sopenharmony_ci } 106bf215546Sopenharmony_ci} 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ciunsigned 109bf215546Sopenharmony_ci_mesa_cpal_compressed_size(int level, GLenum internalFormat, 110bf215546Sopenharmony_ci unsigned width, unsigned height) 111bf215546Sopenharmony_ci{ 112bf215546Sopenharmony_ci const struct cpal_format_info *info; 113bf215546Sopenharmony_ci const int num_levels = -level + 1; 114bf215546Sopenharmony_ci int lvl; 115bf215546Sopenharmony_ci unsigned w, h, expect_size; 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci if (internalFormat < GL_PALETTE4_RGB8_OES 118bf215546Sopenharmony_ci || internalFormat > GL_PALETTE8_RGB5_A1_OES) { 119bf215546Sopenharmony_ci return 0; 120bf215546Sopenharmony_ci } 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci info = &formats[internalFormat - GL_PALETTE4_RGB8_OES]; 123bf215546Sopenharmony_ci assert(info->cpal_format == internalFormat); 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci expect_size = info->palette_size * info->size; 126bf215546Sopenharmony_ci for (lvl = 0; lvl < num_levels; lvl++) { 127bf215546Sopenharmony_ci w = width >> lvl; 128bf215546Sopenharmony_ci if (!w) 129bf215546Sopenharmony_ci w = 1; 130bf215546Sopenharmony_ci h = height >> lvl; 131bf215546Sopenharmony_ci if (!h) 132bf215546Sopenharmony_ci h = 1; 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci if (info->palette_size == 16) 135bf215546Sopenharmony_ci expect_size += (w * h + 1) / 2; 136bf215546Sopenharmony_ci else 137bf215546Sopenharmony_ci expect_size += w * h; 138bf215546Sopenharmony_ci } 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci return expect_size; 141bf215546Sopenharmony_ci} 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci/** 145bf215546Sopenharmony_ci * Convert a call to glCompressedTexImage2D() where internalFormat is a 146bf215546Sopenharmony_ci * compressed palette format into a regular GLubyte/RGBA glTexImage2D() call. 147bf215546Sopenharmony_ci */ 148bf215546Sopenharmony_civoid 149bf215546Sopenharmony_ci_mesa_cpal_compressed_teximage2d(GLenum target, GLint level, 150bf215546Sopenharmony_ci GLenum internalFormat, 151bf215546Sopenharmony_ci GLsizei width, GLsizei height, 152bf215546Sopenharmony_ci GLsizei imageSize, const void *palette) 153bf215546Sopenharmony_ci{ 154bf215546Sopenharmony_ci const struct cpal_format_info *info; 155bf215546Sopenharmony_ci GLint lvl, num_levels; 156bf215546Sopenharmony_ci const GLubyte *indices; 157bf215546Sopenharmony_ci GLint saved_align, align; 158bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci /* By this point, the internalFormat should have been validated. 161bf215546Sopenharmony_ci */ 162bf215546Sopenharmony_ci assert(internalFormat >= GL_PALETTE4_RGB8_OES 163bf215546Sopenharmony_ci && internalFormat <= GL_PALETTE8_RGB5_A1_OES); 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci info = &formats[internalFormat - GL_PALETTE4_RGB8_OES]; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci num_levels = -level + 1; 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci /* first image follows the palette */ 170bf215546Sopenharmony_ci indices = (const GLubyte *) palette + info->palette_size * info->size; 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci saved_align = ctx->Unpack.Alignment; 173bf215546Sopenharmony_ci align = saved_align; 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci for (lvl = 0; lvl < num_levels; lvl++) { 176bf215546Sopenharmony_ci GLsizei w, h; 177bf215546Sopenharmony_ci GLuint num_texels; 178bf215546Sopenharmony_ci GLubyte *image = NULL; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci w = width >> lvl; 181bf215546Sopenharmony_ci if (!w) 182bf215546Sopenharmony_ci w = 1; 183bf215546Sopenharmony_ci h = height >> lvl; 184bf215546Sopenharmony_ci if (!h) 185bf215546Sopenharmony_ci h = 1; 186bf215546Sopenharmony_ci num_texels = w * h; 187bf215546Sopenharmony_ci if (w * info->size % align) { 188bf215546Sopenharmony_ci _mesa_PixelStorei(GL_UNPACK_ALIGNMENT, 1); 189bf215546Sopenharmony_ci align = 1; 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci /* allocate and fill dest image buffer */ 193bf215546Sopenharmony_ci if (palette) { 194bf215546Sopenharmony_ci image = malloc(num_texels * info->size); 195bf215546Sopenharmony_ci paletted_to_color(info, palette, indices, num_texels, image); 196bf215546Sopenharmony_ci } 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci _mesa_TexImage2D(target, lvl, info->format, w, h, 0, 199bf215546Sopenharmony_ci info->format, info->type, image); 200bf215546Sopenharmony_ci free(image); 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci /* advance index pointer to point to next src mipmap */ 203bf215546Sopenharmony_ci if (info->palette_size == 16) 204bf215546Sopenharmony_ci indices += (num_texels + 1) / 2; 205bf215546Sopenharmony_ci else 206bf215546Sopenharmony_ci indices += num_texels; 207bf215546Sopenharmony_ci } 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci if (saved_align != align) 210bf215546Sopenharmony_ci _mesa_PixelStorei(GL_UNPACK_ALIGNMENT, saved_align); 211bf215546Sopenharmony_ci} 212