Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 VMware, Inc.
  4.  * 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
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28.  
  29. #include "main/imports.h"
  30. #include "main/mipmap.h"
  31. #include "main/teximage.h"
  32.  
  33. #include "pipe/p_context.h"
  34. #include "pipe/p_defines.h"
  35. #include "util/u_inlines.h"
  36. #include "util/u_format.h"
  37. #include "util/u_gen_mipmap.h"
  38.  
  39. #include "st_debug.h"
  40. #include "st_context.h"
  41. #include "st_texture.h"
  42. #include "st_gen_mipmap.h"
  43. #include "st_cb_texture.h"
  44.  
  45.  
  46. /**
  47.  * Compute the expected number of mipmap levels in the texture given
  48.  * the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/
  49.  * GL_TEXTURE_MAX_LEVEL settings.  This will tell us how many mipmap
  50.  * levels should be generated.
  51.  */
  52. static GLuint
  53. compute_num_levels(struct gl_context *ctx,
  54.                    struct gl_texture_object *texObj,
  55.                    GLenum target)
  56. {
  57.    const struct gl_texture_image *baseImage;
  58.    GLuint numLevels;
  59.  
  60.    baseImage = _mesa_get_tex_image(ctx, texObj, target, texObj->BaseLevel);
  61.  
  62.    numLevels = texObj->BaseLevel + baseImage->MaxNumLevels;
  63.    numLevels = MIN2(numLevels, (GLuint) texObj->MaxLevel + 1);
  64.    assert(numLevels >= 1);
  65.  
  66.    return numLevels;
  67. }
  68.  
  69.  
  70. /**
  71.  * Called via ctx->Driver.GenerateMipmap().
  72.  */
  73. void
  74. st_generate_mipmap(struct gl_context *ctx, GLenum target,
  75.                    struct gl_texture_object *texObj)
  76. {
  77.    struct st_context *st = st_context(ctx);
  78.    struct st_texture_object *stObj = st_texture_object(texObj);
  79.    struct pipe_resource *pt = st_get_texobj_resource(texObj);
  80.    const uint baseLevel = texObj->BaseLevel;
  81.    uint lastLevel, first_layer, last_layer;
  82.    uint dstLevel;
  83.  
  84.    if (!pt)
  85.       return;
  86.  
  87.    /* not sure if this ultimately actually should work,
  88.       but we're not supporting multisampled textures yet. */
  89.    assert(pt->nr_samples < 2);
  90.  
  91.    /* find expected last mipmap level to generate*/
  92.    lastLevel = compute_num_levels(ctx, texObj, target) - 1;
  93.  
  94.    if (lastLevel == 0)
  95.       return;
  96.  
  97.    /* The texture isn't in a "complete" state yet so set the expected
  98.     * lastLevel here, since it won't get done in st_finalize_texture().
  99.     */
  100.    stObj->lastLevel = lastLevel;
  101.  
  102.    if (pt->last_level < lastLevel) {
  103.       /* The current gallium texture doesn't have space for all the
  104.        * mipmap levels we need to generate.  So allocate a new texture.
  105.        */
  106.       struct pipe_resource *oldTex = stObj->pt;
  107.  
  108.       /* create new texture with space for more levels */
  109.       stObj->pt = st_texture_create(st,
  110.                                     oldTex->target,
  111.                                     oldTex->format,
  112.                                     lastLevel,
  113.                                     oldTex->width0,
  114.                                     oldTex->height0,
  115.                                     oldTex->depth0,
  116.                                     oldTex->array_size,
  117.                                     0,
  118.                                     oldTex->bind);
  119.  
  120.       /* This will copy the old texture's base image into the new texture
  121.        * which we just allocated.
  122.        */
  123.       st_finalize_texture(ctx, st->pipe, texObj);
  124.  
  125.       /* release the old tex (will likely be freed too) */
  126.       pipe_resource_reference(&oldTex, NULL);
  127.       st_texture_release_all_sampler_views(st, stObj);
  128.    }
  129.    else {
  130.       /* Make sure that the base texture image data is present in the
  131.        * texture buffer.
  132.        */
  133.       st_finalize_texture(ctx, st->pipe, texObj);
  134.    }
  135.  
  136.    pt = stObj->pt;
  137.  
  138.    assert(pt->last_level >= lastLevel);
  139.  
  140.    if (pt->target == PIPE_TEXTURE_CUBE) {
  141.       first_layer = last_layer = _mesa_tex_target_to_face(target);
  142.    }
  143.    else {
  144.       first_layer = 0;
  145.       last_layer = util_max_layer(pt, baseLevel);
  146.    }
  147.  
  148.    /* Try to generate the mipmap by rendering/texturing.  If that fails,
  149.     * use the software fallback.
  150.     */
  151.    if (!util_gen_mipmap(st->pipe, pt, pt->format, baseLevel, lastLevel,
  152.                         first_layer, last_layer, PIPE_TEX_FILTER_LINEAR)) {
  153.       _mesa_generate_mipmap(ctx, target, texObj);
  154.    }
  155.  
  156.    /* Fill in the Mesa gl_texture_image fields */
  157.    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
  158.       const uint srcLevel = dstLevel - 1;
  159.       const struct gl_texture_image *srcImage
  160.          = _mesa_get_tex_image(ctx, texObj, target, srcLevel);
  161.       struct gl_texture_image *dstImage;
  162.       struct st_texture_image *stImage;
  163.       uint border = srcImage->Border;
  164.       uint dstWidth, dstHeight, dstDepth;
  165.  
  166.       dstWidth = u_minify(pt->width0, dstLevel);
  167.       if (texObj->Target == GL_TEXTURE_1D_ARRAY) {
  168.          dstHeight = pt->array_size;
  169.       }
  170.       else {
  171.          dstHeight = u_minify(pt->height0, dstLevel);
  172.       }
  173.       if (texObj->Target == GL_TEXTURE_2D_ARRAY ||
  174.           texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) {
  175.          dstDepth = pt->array_size;
  176.       }
  177.       else {
  178.          dstDepth = u_minify(pt->depth0, dstLevel);
  179.       }
  180.  
  181.       dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel);
  182.       if (!dstImage) {
  183.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
  184.          return;
  185.       }
  186.  
  187.       /* Free old image data */
  188.       ctx->Driver.FreeTextureImageBuffer(ctx, dstImage);
  189.  
  190.       /* initialize new image */
  191.       _mesa_init_teximage_fields(ctx, dstImage, dstWidth, dstHeight,
  192.                                  dstDepth, border, srcImage->InternalFormat,
  193.                                  srcImage->TexFormat);
  194.  
  195.       stImage = st_texture_image(dstImage);
  196.  
  197.       pipe_resource_reference(&stImage->pt, pt);
  198.    }
  199. }
  200.