Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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