Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  *
  6.  **************************************************************************/
  7.  
  8.  
  9. /**
  10.  * Code to convert compressed/paletted texture images to ordinary images.
  11.  * See the GL_OES_compressed_paletted_texture spec at
  12.  * http://khronos.org/registry/gles/extensions/OES/OES_compressed_paletted_texture.txt
  13.  *
  14.  * XXX this makes it impossible to add hardware support...
  15.  */
  16.  
  17.  
  18. #include "glheader.h"
  19. #include "compiler.h" /* for ASSERT */
  20. #include "context.h"
  21. #include "mtypes.h"
  22. #include "imports.h"
  23. #include "pixelstore.h"
  24. #include "teximage.h"
  25. #include "texpal.h"
  26.  
  27. #if FEATURE_ES
  28.  
  29.  
  30. static const struct cpal_format_info {
  31.    GLenum cpal_format;
  32.    GLenum format;
  33.    GLenum type;
  34.    GLuint palette_size;
  35.    GLuint size;
  36. } formats[] = {
  37.    { GL_PALETTE4_RGB8_OES,     GL_RGB,  GL_UNSIGNED_BYTE,           16, 3 },
  38.    { GL_PALETTE4_RGBA8_OES,    GL_RGBA, GL_UNSIGNED_BYTE,           16, 4 },
  39.    { GL_PALETTE4_R5_G6_B5_OES, GL_RGB,  GL_UNSIGNED_SHORT_5_6_5,    16, 2 },
  40.    { GL_PALETTE4_RGBA4_OES,    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,  16, 2 },
  41.    { GL_PALETTE4_RGB5_A1_OES,  GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1,  16, 2 },
  42.    { GL_PALETTE8_RGB8_OES,     GL_RGB,  GL_UNSIGNED_BYTE,          256, 3 },
  43.    { GL_PALETTE8_RGBA8_OES,    GL_RGBA, GL_UNSIGNED_BYTE,          256, 4 },
  44.    { GL_PALETTE8_R5_G6_B5_OES, GL_RGB,  GL_UNSIGNED_SHORT_5_6_5,   256, 2 },
  45.    { GL_PALETTE8_RGBA4_OES,    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 256, 2 },
  46.    { GL_PALETTE8_RGB5_A1_OES,  GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 256, 2 }
  47. };
  48.  
  49.  
  50. /**
  51.  * Get a color/entry from the palette.
  52.  */
  53. static GLuint
  54. get_palette_entry(const struct cpal_format_info *info, const GLubyte *palette,
  55.                   GLuint index, GLubyte *pixel)
  56. {
  57.    memcpy(pixel, palette + info->size * index, info->size);
  58.    return info->size;
  59. }
  60.  
  61.  
  62. /**
  63.  * Convert paletted texture to color texture.
  64.  */
  65. static void
  66. paletted_to_color(const struct cpal_format_info *info, const GLubyte *palette,
  67.                   const void *indices, GLuint num_pixels, GLubyte *image)
  68. {
  69.    GLubyte *pix = image;
  70.    GLuint remain, i;
  71.  
  72.    if (info->palette_size == 16) {
  73.       /* 4 bits per index */
  74.       const GLubyte *ind = (const GLubyte *) indices;
  75.  
  76.       /* two pixels per iteration */
  77.       remain = num_pixels % 2;
  78.       for (i = 0; i < num_pixels / 2; i++) {
  79.          pix += get_palette_entry(info, palette, (ind[i] >> 4) & 0xf, pix);
  80.          pix += get_palette_entry(info, palette, ind[i] & 0xf, pix);
  81.       }
  82.       if (remain) {
  83.          get_palette_entry(info, palette, (ind[i] >> 4) & 0xf, pix);
  84.       }
  85.    }
  86.    else {
  87.       /* 8 bits per index */
  88.       const GLubyte *ind = (const GLubyte *) indices;
  89.       for (i = 0; i < num_pixels; i++)
  90.          pix += get_palette_entry(info, palette, ind[i], pix);
  91.    }
  92. }
  93.  
  94.  
  95. static const struct cpal_format_info *
  96. cpal_get_info(GLint level, GLenum internalFormat,
  97.               GLsizei width, GLsizei height, GLsizei imageSize)
  98. {
  99.    const struct cpal_format_info *info;
  100.    GLint lvl, num_levels;
  101.    GLsizei w, h, expect_size;
  102.  
  103.    info = &formats[internalFormat - GL_PALETTE4_RGB8_OES];
  104.    ASSERT(info->cpal_format == internalFormat);
  105.  
  106.    if (level > 0) {
  107.       _mesa_error(_mesa_get_current_context(), GL_INVALID_VALUE,
  108.             "glCompressedTexImage2D(level=%d)", level);
  109.       return NULL;
  110.    }
  111.  
  112.    num_levels = -level + 1;
  113.    expect_size = info->palette_size * info->size;
  114.    for (lvl = 0; lvl < num_levels; lvl++) {
  115.       w = width >> lvl;
  116.       if (!w)
  117.          w = 1;
  118.       h = height >> lvl;
  119.       if (!h)
  120.          h = 1;
  121.  
  122.       if (info->palette_size == 16)
  123.          expect_size += (w * h  + 1) / 2;
  124.       else
  125.          expect_size += w * h;
  126.    }
  127.    if (expect_size > imageSize) {
  128.       _mesa_error(_mesa_get_current_context(), GL_INVALID_VALUE,
  129.             "glCompressedTexImage2D(imageSize=%d)", imageSize);
  130.       return NULL;
  131.    }
  132.    return info;
  133. }
  134.  
  135. /**
  136.  * Convert a call to glCompressedTexImage2D() where internalFormat is a
  137.  *  compressed palette format into a regular GLubyte/RGBA glTexImage2D() call.
  138.  */
  139. void
  140. _mesa_cpal_compressed_teximage2d(GLenum target, GLint level,
  141.                                  GLenum internalFormat,
  142.                                  GLsizei width, GLsizei height,
  143.                                  GLsizei imageSize, const void *palette)
  144. {
  145.    const struct cpal_format_info *info;
  146.    GLint lvl, num_levels;
  147.    const GLubyte *indices;
  148.    GLint saved_align, align;
  149.    GET_CURRENT_CONTEXT(ctx);
  150.  
  151.    info = cpal_get_info(level, internalFormat, width, height, imageSize);
  152.    if (!info)
  153.       return;
  154.  
  155.    info = &formats[internalFormat - GL_PALETTE4_RGB8_OES];
  156.    ASSERT(info->cpal_format == internalFormat);
  157.    num_levels = -level + 1;
  158.  
  159.    /* first image follows the palette */
  160.    indices = (const GLubyte *) palette + info->palette_size * info->size;
  161.  
  162.    saved_align = ctx->Unpack.Alignment;
  163.    align = saved_align;
  164.  
  165.    for (lvl = 0; lvl < num_levels; lvl++) {
  166.       GLsizei w, h;
  167.       GLuint num_texels;
  168.       GLubyte *image = NULL;
  169.  
  170.       w = width >> lvl;
  171.       if (!w)
  172.          w = 1;
  173.       h = height >> lvl;
  174.       if (!h)
  175.          h = 1;
  176.       num_texels = w * h;
  177.       if (w * info->size % align) {
  178.          _mesa_PixelStorei(GL_UNPACK_ALIGNMENT, 1);
  179.          align = 1;
  180.       }
  181.  
  182.       /* allocate and fill dest image buffer */
  183.       if (palette) {
  184.          image = (GLubyte *) malloc(num_texels * info->size);
  185.          paletted_to_color(info, palette, indices, num_texels, image);
  186.       }
  187.  
  188.       _mesa_TexImage2D(target, lvl, info->format, w, h, 0,
  189.                        info->format, info->type, image);
  190.       if (image)
  191.          free(image);
  192.  
  193.       /* advance index pointer to point to next src mipmap */
  194.       if (info->palette_size == 16)
  195.          indices += (num_texels + 1) / 2;
  196.       else
  197.          indices += num_texels;
  198.    }
  199.  
  200.    if (saved_align != align)
  201.       _mesa_PixelStorei(GL_UNPACK_ALIGNMENT, saved_align);
  202. }
  203.  
  204. #endif
  205.