Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 2011  VMware, Inc.  All Rights Reserved.
  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. /**
  27.  * \file texstorage.c
  28.  * GL_ARB_texture_storage functions
  29.  */
  30.  
  31.  
  32.  
  33. #include "glheader.h"
  34. #include "context.h"
  35. #include "enums.h"
  36. #include "imports.h"
  37. #include "macros.h"
  38. #include "teximage.h"
  39. #include "texobj.h"
  40. #include "texstorage.h"
  41. #include "mtypes.h"
  42.  
  43.  
  44.  
  45. /**
  46.  * Check if the given texture target is a legal texture object target
  47.  * for a glTexStorage() command.
  48.  * This is a bit different than legal_teximage_target() when it comes
  49.  * to cube maps.
  50.  */
  51. static GLboolean
  52. legal_texobj_target(struct gl_context *ctx, GLuint dims, GLenum target)
  53. {
  54.    switch (dims) {
  55.    case 1:
  56.       switch (target) {
  57.       case GL_TEXTURE_1D:
  58.       case GL_PROXY_TEXTURE_1D:
  59.          return GL_TRUE;
  60.       default:
  61.          return GL_FALSE;
  62.       }
  63.    case 2:
  64.       switch (target) {
  65.       case GL_TEXTURE_2D:
  66.       case GL_PROXY_TEXTURE_2D:
  67.          return GL_TRUE;
  68.       case GL_TEXTURE_CUBE_MAP:
  69.       case GL_PROXY_TEXTURE_CUBE_MAP:
  70.          return ctx->Extensions.ARB_texture_cube_map;
  71.       case GL_TEXTURE_RECTANGLE:
  72.       case GL_PROXY_TEXTURE_RECTANGLE:
  73.          return ctx->Extensions.NV_texture_rectangle;
  74.       case GL_TEXTURE_1D_ARRAY:
  75.       case GL_PROXY_TEXTURE_1D_ARRAY:
  76.          return (ctx->Extensions.MESA_texture_array ||
  77.                  ctx->Extensions.EXT_texture_array);
  78.       default:
  79.          return GL_FALSE;
  80.       }
  81.    case 3:
  82.       switch (target) {
  83.       case GL_TEXTURE_3D:
  84.       case GL_PROXY_TEXTURE_3D:
  85.          return GL_TRUE;
  86.       case GL_TEXTURE_2D_ARRAY:
  87.       case GL_PROXY_TEXTURE_2D_ARRAY:
  88.          return (ctx->Extensions.MESA_texture_array ||
  89.                  ctx->Extensions.EXT_texture_array);
  90.       case GL_TEXTURE_CUBE_MAP_ARRAY:
  91.       case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
  92.          return ctx->Extensions.ARB_texture_cube_map_array;
  93.       default:
  94.          return GL_FALSE;
  95.       }
  96.    default:
  97.       _mesa_problem(ctx, "invalid dims=%u in legal_texobj_target()", dims);
  98.       return GL_FALSE;
  99.    }
  100. }
  101.  
  102.  
  103. /**
  104.  * Compute the size of the next mipmap level.
  105.  */
  106. static void
  107. next_mipmap_level_size(GLenum target,
  108.                        GLint *width, GLint *height, GLint *depth)
  109. {
  110.    if (*width > 1) {
  111.       *width /= 2;
  112.    }
  113.  
  114.    if ((*height > 1) && (target != GL_TEXTURE_1D_ARRAY)) {
  115.       *height /= 2;
  116.    }
  117.  
  118.    if ((*depth > 1) && (target != GL_TEXTURE_2D_ARRAY)) {
  119.       *depth /= 2;
  120.    }
  121. }
  122.  
  123.  
  124. /** Helper to get a particular texture image in a texture object */
  125. static struct gl_texture_image *
  126. get_tex_image(struct gl_context *ctx,
  127.               struct gl_texture_object *texObj,
  128.               GLuint face, GLuint level)
  129. {
  130.    const GLenum faceTarget =
  131.       (texObj->Target == GL_TEXTURE_CUBE_MAP ||
  132.        texObj->Target == GL_PROXY_TEXTURE_CUBE_MAP)
  133.       ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : texObj->Target;
  134.    return _mesa_get_tex_image(ctx, texObj, faceTarget, level);
  135. }
  136.  
  137.  
  138.  
  139. static GLboolean
  140. initialize_texture_fields(struct gl_context *ctx,
  141.                           struct gl_texture_object *texObj,
  142.                           GLint levels,
  143.                           GLsizei width, GLsizei height, GLsizei depth,
  144.                           GLenum internalFormat, gl_format texFormat)
  145. {
  146.    const GLenum target = texObj->Target;
  147.    const GLuint numFaces = _mesa_num_tex_faces(target);
  148.    GLint level, levelWidth = width, levelHeight = height, levelDepth = depth;
  149.    GLuint face;
  150.  
  151.    /* Set up all the texture object's gl_texture_images */
  152.    for (level = 0; level < levels; level++) {
  153.       for (face = 0; face < numFaces; face++) {
  154.          struct gl_texture_image *texImage =
  155.             get_tex_image(ctx, texObj, face, level);
  156.  
  157.          if (!texImage) {
  158.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
  159.             return GL_FALSE;
  160.          }
  161.  
  162.          _mesa_init_teximage_fields(ctx, texImage,
  163.                                     levelWidth, levelHeight, levelDepth,
  164.                                     0, internalFormat, texFormat);
  165.       }
  166.  
  167.       next_mipmap_level_size(target, &levelWidth, &levelHeight, &levelDepth);
  168.    }
  169.    return GL_TRUE;
  170. }
  171.  
  172.  
  173. /**
  174.  * Clear all fields of texture object to zeros.  Used for proxy texture tests.
  175.  * Used for proxy texture tests (and to clean up when a texture memory
  176.  * allocation fails).
  177.  */
  178. static void
  179. clear_texture_fields(struct gl_context *ctx,
  180.                      struct gl_texture_object *texObj)
  181. {
  182.    const GLenum target = texObj->Target;
  183.    const GLuint numFaces = _mesa_num_tex_faces(target);
  184.    GLint level;
  185.    GLuint face;
  186.  
  187.    for (level = 0; level < Elements(texObj->Image[0]); level++) {
  188.       for (face = 0; face < numFaces; face++) {
  189.          struct gl_texture_image *texImage =
  190.             get_tex_image(ctx, texObj, face, level);
  191.  
  192.          if (!texImage) {
  193.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
  194.             return;
  195.          }
  196.  
  197.          _mesa_init_teximage_fields(ctx, texImage,
  198.                                     0, 0, 0, 0, /* w, h, d, border */
  199.                                     GL_NONE, MESA_FORMAT_NONE);
  200.       }
  201.    }
  202. }
  203.  
  204.  
  205. GLboolean
  206. _mesa_is_legal_tex_storage_format(struct gl_context *ctx, GLenum internalformat)
  207. {
  208.    /* check internal format - note that only sized formats are allowed */
  209.    switch (internalformat) {
  210.    case GL_ALPHA:
  211.    case GL_LUMINANCE:
  212.    case GL_LUMINANCE_ALPHA:
  213.    case GL_INTENSITY:
  214.    case GL_RED:
  215.    case GL_RG:
  216.    case GL_RGB:
  217.    case GL_RGBA:
  218.    case GL_BGRA:
  219.    case GL_DEPTH_COMPONENT:
  220.    case GL_DEPTH_STENCIL:
  221.    case GL_COMPRESSED_ALPHA:
  222.    case GL_COMPRESSED_LUMINANCE_ALPHA:
  223.    case GL_COMPRESSED_LUMINANCE:
  224.    case GL_COMPRESSED_INTENSITY:
  225.    case GL_COMPRESSED_RGB:
  226.    case GL_COMPRESSED_RGBA:
  227.    case GL_COMPRESSED_SRGB:
  228.    case GL_COMPRESSED_SRGB_ALPHA:
  229.    case GL_COMPRESSED_SLUMINANCE:
  230.    case GL_COMPRESSED_SLUMINANCE_ALPHA:
  231.    case GL_RED_INTEGER:
  232.    case GL_GREEN_INTEGER:
  233.    case GL_BLUE_INTEGER:
  234.    case GL_ALPHA_INTEGER:
  235.    case GL_RGB_INTEGER:
  236.    case GL_RGBA_INTEGER:
  237.    case GL_BGR_INTEGER:
  238.    case GL_BGRA_INTEGER:
  239.    case GL_LUMINANCE_INTEGER_EXT:
  240.    case GL_LUMINANCE_ALPHA_INTEGER_EXT:
  241.       /* these unsized formats are illegal */
  242.       return GL_FALSE;
  243.    default:
  244.       return _mesa_base_tex_format(ctx, internalformat) > 0;
  245.    }
  246. }
  247.  
  248. /**
  249.  * Default ctx->Driver.AllocTextureStorage() handler.
  250.  *
  251.  * The driver can override this with a more specific implementation if it
  252.  * desires, but this can be used to get the texture images allocated using the
  253.  * usual texture image handling code.  The immutability of
  254.  * GL_ARB_texture_storage texture layouts is handled by texObj->Immutable
  255.  * checks at glTexImage* time.
  256.  */
  257. GLboolean
  258. _mesa_alloc_texture_storage(struct gl_context *ctx,
  259.                             struct gl_texture_object *texObj,
  260.                             GLsizei levels, GLsizei width,
  261.                             GLsizei height, GLsizei depth)
  262. {
  263.    const int numFaces = _mesa_num_tex_faces(texObj->Target);
  264.    int face;
  265.    int level;
  266.  
  267.    for (face = 0; face < numFaces; face++) {
  268.       for (level = 0; level < levels; level++) {
  269.          struct gl_texture_image *const texImage = texObj->Image[face][level];
  270.          if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage))
  271.             return GL_FALSE;
  272.       }
  273.    }
  274.  
  275.    return GL_TRUE;
  276. }
  277.  
  278.  
  279. /**
  280.  * Do error checking for calls to glTexStorage1/2/3D().
  281.  * If an error is found, record it with _mesa_error(), unless the target
  282.  * is a proxy texture.
  283.  * \return GL_TRUE if any error, GL_FALSE otherwise.
  284.  */
  285. static GLboolean
  286. tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target,
  287.                         GLsizei levels, GLenum internalformat,
  288.                         GLsizei width, GLsizei height, GLsizei depth)
  289. {
  290.    struct gl_texture_object *texObj;
  291.  
  292.    if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
  293.       _mesa_error(ctx, GL_INVALID_ENUM,
  294.                   "glTexStorage%uD(internalformat = %s)", dims,
  295.                   _mesa_lookup_enum_by_nr(internalformat));
  296.       return GL_TRUE;
  297.    }
  298.  
  299.    /* size check */
  300.    if (width < 1 || height < 1 || depth < 1) {
  301.       _mesa_error(ctx, GL_INVALID_VALUE,
  302.                   "glTexStorage%uD(width, height or depth < 1)", dims);
  303.       return GL_TRUE;
  304.    }  
  305.  
  306.    /* target check */
  307.    if (!legal_texobj_target(ctx, dims, target)) {
  308.       _mesa_error(ctx, GL_INVALID_ENUM,
  309.                   "glTexStorage%uD(illegal target=%s)",
  310.                   dims, _mesa_lookup_enum_by_nr(target));
  311.       return GL_TRUE;
  312.    }
  313.  
  314.    /* levels check */
  315.    if (levels < 1) {
  316.       _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)",
  317.                   dims);
  318.       return GL_TRUE;
  319.    }  
  320.  
  321.    /* check levels against maximum (note different error than above) */
  322.    if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) {
  323.       _mesa_error(ctx, GL_INVALID_OPERATION,
  324.                   "glTexStorage%uD(levels too large)", dims);
  325.       return GL_TRUE;
  326.    }
  327.  
  328.    /* check levels against width/height/depth */
  329.    if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) {
  330.       _mesa_error(ctx, GL_INVALID_OPERATION,
  331.                   "glTexStorage%uD(too many levels for max texture dimension)",
  332.                   dims);
  333.       return GL_TRUE;
  334.    }
  335.  
  336.    /* non-default texture object check */
  337.    texObj = _mesa_get_current_tex_object(ctx, target);
  338.    if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) {
  339.       _mesa_error(ctx, GL_INVALID_OPERATION,
  340.                   "glTexStorage%uD(texture object 0)", dims);
  341.       return GL_TRUE;
  342.    }
  343.  
  344.    /* Check if texObj->Immutable is set */
  345.    if (!_mesa_is_proxy_texture(target) && texObj->Immutable) {
  346.       _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(immutable)",
  347.                   dims);
  348.       return GL_TRUE;
  349.    }
  350.  
  351.    return GL_FALSE;
  352. }
  353.  
  354.  
  355. /**
  356.  * Helper used by _mesa_TexStorage1/2/3D().
  357.  */
  358. static void
  359. texstorage(GLuint dims, GLenum target, GLsizei levels, GLenum internalformat,
  360.            GLsizei width, GLsizei height, GLsizei depth)
  361. {
  362.    struct gl_texture_object *texObj;
  363.    GLboolean sizeOK, dimensionsOK;
  364.    gl_format texFormat;
  365.  
  366.    GET_CURRENT_CONTEXT(ctx);
  367.  
  368.    if (tex_storage_error_check(ctx, dims, target, levels,
  369.                                internalformat, width, height, depth)) {
  370.       return; /* error was recorded */
  371.    }
  372.  
  373.    texObj = _mesa_get_current_tex_object(ctx, target);
  374.    assert(texObj);
  375.  
  376.    texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0,
  377.                                            internalformat, GL_NONE, GL_NONE);
  378.    assert(texFormat != MESA_FORMAT_NONE);
  379.  
  380.    /* check that width, height, depth are legal for the mipmap level */
  381.    dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0,
  382.                                                   width, height, depth, 0);
  383.  
  384.    sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 0, texFormat,
  385.                                           width, height, depth, 0);
  386.  
  387.    if (_mesa_is_proxy_texture(texObj->Target)) {
  388.       if (dimensionsOK && sizeOK) {
  389.          initialize_texture_fields(ctx, texObj, levels, width, height, depth,
  390.                                    internalformat, texFormat);
  391.       }
  392.       else {
  393.          /* clear all image fields for [levels] */
  394.          clear_texture_fields(ctx, texObj);
  395.       }
  396.    }
  397.    else {
  398.       if (!dimensionsOK) {
  399.          _mesa_error(ctx, GL_INVALID_VALUE,
  400.                      "glTexStorage%uD(invalid width, height or depth)", dims);
  401.          return;
  402.       }
  403.  
  404.       if (!sizeOK) {
  405.          _mesa_error(ctx, GL_OUT_OF_MEMORY,
  406.                      "glTexStorage%uD(texture too large)", dims);
  407.       }
  408.  
  409.       assert(levels > 0);
  410.       assert(width > 0);
  411.       assert(height > 0);
  412.       assert(depth > 0);
  413.  
  414.       if (!initialize_texture_fields(ctx, texObj, levels, width, height, depth,
  415.                                      internalformat, texFormat)) {
  416.          return;
  417.       }
  418.  
  419.       /* Do actual texture memory allocation */
  420.       if (!ctx->Driver.AllocTextureStorage(ctx, texObj, levels,
  421.                                            width, height, depth)) {
  422.          /* Reset the texture images' info to zeros.
  423.           * Strictly speaking, we probably don't have to do this since
  424.           * generating GL_OUT_OF_MEMORY can leave things in an undefined
  425.           * state but this puts things in a consistent state.
  426.           */
  427.          clear_texture_fields(ctx, texObj);
  428.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage%uD", dims);
  429.          return;
  430.       }
  431.  
  432.       texObj->Immutable = GL_TRUE;
  433.       texObj->ImmutableLevels = levels;
  434.    }
  435. }
  436.  
  437.  
  438. void GLAPIENTRY
  439. _mesa_TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat,
  440.                    GLsizei width)
  441. {
  442.    texstorage(1, target, levels, internalformat, width, 1, 1);
  443. }
  444.  
  445.  
  446. void GLAPIENTRY
  447. _mesa_TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat,
  448.                    GLsizei width, GLsizei height)
  449. {
  450.    texstorage(2, target, levels, internalformat, width, height, 1);
  451. }
  452.  
  453.  
  454. void GLAPIENTRY
  455. _mesa_TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
  456.                    GLsizei width, GLsizei height, GLsizei depth)
  457. {
  458.    texstorage(3, target, levels, internalformat, width, height, depth);
  459. }
  460.  
  461.  
  462.  
  463. /*
  464.  * Note: we don't support GL_EXT_direct_state_access and the spec says
  465.  * we don't need the following functions.  However, glew checks for the
  466.  * presence of all six functions and will say that GL_ARB_texture_storage
  467.  * is not supported if these functions are missing.
  468.  */
  469.  
  470.  
  471. void GLAPIENTRY
  472. _mesa_TextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels,
  473.                           GLenum internalformat,
  474.                           GLsizei width)
  475. {
  476.    /* no-op */
  477. }
  478.  
  479.  
  480. void GLAPIENTRY
  481. _mesa_TextureStorage2DEXT(GLuint texture, GLenum target, GLsizei levels,
  482.                           GLenum internalformat,
  483.                           GLsizei width, GLsizei height)
  484. {
  485.    /* no-op */
  486. }
  487.  
  488.  
  489.  
  490. void GLAPIENTRY
  491. _mesa_TextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels,
  492.                           GLenum internalformat,
  493.                           GLsizei width, GLsizei height, GLsizei depth)
  494. {
  495.    /* no-op */
  496. }
  497.