Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  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 TUNGSTEN GRAPHICS 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. #include <stdio.h>
  29.  
  30. #include "st_context.h"
  31. #include "st_format.h"
  32. #include "st_texture.h"
  33. #include "st_cb_fbo.h"
  34. #include "main/enums.h"
  35.  
  36. #include "pipe/p_state.h"
  37. #include "pipe/p_context.h"
  38. #include "pipe/p_defines.h"
  39. #include "util/u_inlines.h"
  40. #include "util/u_format.h"
  41. #include "util/u_rect.h"
  42. #include "util/u_math.h"
  43.  
  44.  
  45. #define DBG if(0) printf
  46.  
  47.  
  48. /**
  49.  * Allocate a new pipe_resource object
  50.  * width0, height0, depth0 are the dimensions of the level 0 image
  51.  * (the highest resolution).  last_level indicates how many mipmap levels
  52.  * to allocate storage for.  For non-mipmapped textures, this will be zero.
  53.  */
  54. struct pipe_resource *
  55. st_texture_create(struct st_context *st,
  56.                   enum pipe_texture_target target,
  57.                   enum pipe_format format,
  58.                   GLuint last_level,
  59.                   GLuint width0,
  60.                   GLuint height0,
  61.                   GLuint depth0,
  62.                   GLuint bind )
  63. {
  64.    struct pipe_resource pt, *newtex;
  65.    struct pipe_screen *screen = st->pipe->screen;
  66.  
  67.    assert(target < PIPE_MAX_TEXTURE_TYPES);
  68.    assert(width0 > 0);
  69.    assert(height0 > 0);
  70.    assert(depth0 > 0);
  71.  
  72.    DBG("%s target %s format %s last_level %d\n", __FUNCTION__,
  73.        _mesa_lookup_enum_by_nr(target),
  74.        _mesa_lookup_enum_by_nr(format), last_level);
  75.  
  76.    assert(format);
  77.    assert(screen->is_format_supported(screen, format, target, 0,
  78.                                       PIPE_BIND_SAMPLER_VIEW, 0));
  79.  
  80.    memset(&pt, 0, sizeof(pt));
  81.    pt.target = target;
  82.    pt.format = format;
  83.    pt.last_level = last_level;
  84.    pt.width0 = width0;
  85.    pt.height0 = height0;
  86.    pt.depth0 = depth0;
  87.    pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : 1);
  88.    pt.usage = PIPE_USAGE_DEFAULT;
  89.    pt.bind = bind;
  90.    pt.flags = 0;
  91.  
  92.    newtex = screen->resource_create(screen, &pt);
  93.  
  94.    assert(!newtex || pipe_is_referenced(&newtex->reference));
  95.  
  96.    return newtex;
  97. }
  98.  
  99.  
  100. /**
  101.  * Check if a texture image can be pulled into a unified mipmap texture.
  102.  */
  103. GLboolean
  104. st_texture_match_image(const struct pipe_resource *pt,
  105.                        const struct gl_texture_image *image,
  106.                        GLuint face, GLuint level)
  107. {
  108.    /* Images with borders are never pulled into mipmap textures.
  109.     */
  110.    if (image->Border)
  111.       return GL_FALSE;
  112.  
  113.    /* Check if this image's format matches the established texture's format.
  114.     */
  115.    if (st_mesa_format_to_pipe_format(image->TexFormat) != pt->format)
  116.       return GL_FALSE;
  117.  
  118.    /* Test if this image's size matches what's expected in the
  119.     * established texture.
  120.     */
  121.    if (image->Width != u_minify(pt->width0, level) ||
  122.        image->Height != u_minify(pt->height0, level) ||
  123.        image->Depth != u_minify(pt->depth0, level))
  124.       return GL_FALSE;
  125.  
  126.    return GL_TRUE;
  127. }
  128.  
  129.  
  130. /**
  131.  * Map a texture image and return the address for a particular 2D face/slice/
  132.  * layer.  The stImage indicates the cube face and mipmap level.  The slice
  133.  * of the 3D texture is passed in 'zoffset'.
  134.  * \param usage  one of the PIPE_TRANSFER_x values
  135.  * \param x, y, w, h  the region of interest of the 2D image.
  136.  * \return address of mapping or NULL if any error
  137.  */
  138. GLubyte *
  139. st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
  140.                      GLuint zoffset, enum pipe_transfer_usage usage,
  141.                      GLuint x, GLuint y, GLuint w, GLuint h)
  142. {
  143.    struct pipe_context *pipe = st->pipe;
  144.    struct pipe_resource *pt = stImage->pt;
  145.  
  146.    DBG("%s \n", __FUNCTION__);
  147.  
  148.    stImage->transfer = pipe_get_transfer(st->pipe, pt, stImage->level,
  149.                                          stImage->face + zoffset,
  150.                                          usage, x, y, w, h);
  151.  
  152.    if (stImage->transfer)
  153.       return pipe_transfer_map(pipe, stImage->transfer);
  154.    else
  155.       return NULL;
  156. }
  157.  
  158.  
  159. void
  160. st_texture_image_unmap(struct st_context *st,
  161.                        struct st_texture_image *stImage)
  162. {
  163.    struct pipe_context *pipe = st->pipe;
  164.  
  165.    DBG("%s\n", __FUNCTION__);
  166.  
  167.    pipe_transfer_unmap(pipe, stImage->transfer);
  168.  
  169.    pipe->transfer_destroy(pipe, stImage->transfer);
  170. }
  171.  
  172.  
  173.  
  174. /**
  175.  * Upload data to a rectangular sub-region.  Lots of choices how to do this:
  176.  *
  177.  * - memcpy by span to current destination
  178.  * - upload data as new buffer and blit
  179.  *
  180.  * Currently always memcpy.
  181.  */
  182. static void
  183. st_surface_data(struct pipe_context *pipe,
  184.                 struct pipe_transfer *dst,
  185.                 unsigned dstx, unsigned dsty,
  186.                 const void *src, unsigned src_stride,
  187.                 unsigned srcx, unsigned srcy, unsigned width, unsigned height)
  188. {
  189.    void *map = pipe_transfer_map(pipe, dst);
  190.  
  191.    assert(dst->resource);
  192.    util_copy_rect(map,
  193.                   dst->resource->format,
  194.                   dst->stride,
  195.                   dstx, dsty,
  196.                   width, height,
  197.                   src, src_stride,
  198.                   srcx, srcy);
  199.  
  200.    pipe_transfer_unmap(pipe, dst);
  201. }
  202.  
  203.  
  204. /* Upload data for a particular image.
  205.  */
  206. void
  207. st_texture_image_data(struct st_context *st,
  208.                       struct pipe_resource *dst,
  209.                       GLuint face,
  210.                       GLuint level,
  211.                       void *src,
  212.                       GLuint src_row_stride, GLuint src_image_stride)
  213. {
  214.    struct pipe_context *pipe = st->pipe;
  215.    GLuint depth = u_minify(dst->depth0, level);
  216.    GLuint i;
  217.    const GLubyte *srcUB = src;
  218.    struct pipe_transfer *dst_transfer;
  219.  
  220.    DBG("%s\n", __FUNCTION__);
  221.  
  222.    for (i = 0; i < depth; i++) {
  223.       dst_transfer = pipe_get_transfer(st->pipe, dst, level, face + i,
  224.                                        PIPE_TRANSFER_WRITE, 0, 0,
  225.                                        u_minify(dst->width0, level),
  226.                                        u_minify(dst->height0, level));
  227.  
  228.       st_surface_data(pipe, dst_transfer,
  229.                       0, 0,                             /* dstx, dsty */
  230.                       srcUB,
  231.                       src_row_stride,
  232.                       0, 0,                             /* source x, y */
  233.                       u_minify(dst->width0, level),
  234.                       u_minify(dst->height0, level));    /* width, height */
  235.  
  236.       pipe->transfer_destroy(pipe, dst_transfer);
  237.  
  238.       srcUB += src_image_stride;
  239.    }
  240. }
  241.  
  242.  
  243. /**
  244.  * For debug only: get/print center pixel in the src resource.
  245.  */
  246. static void
  247. print_center_pixel(struct pipe_context *pipe, struct pipe_resource *src)
  248. {
  249.    struct pipe_transfer *xfer;
  250.    struct pipe_box region;
  251.    ubyte *map;
  252.  
  253.    region.x = src->width0 / 2;
  254.    region.y = src->height0 / 2;
  255.    region.z = 0;
  256.    region.width = 1;
  257.    region.height = 1;
  258.    region.depth = 1;
  259.  
  260.    xfer = pipe->get_transfer(pipe, src, 0, PIPE_TRANSFER_READ, &region);
  261.    map = pipe->transfer_map(pipe, xfer);
  262.  
  263.    printf("center pixel: %d %d %d %d\n", map[0], map[1], map[2], map[3]);
  264.  
  265.    pipe->transfer_unmap(pipe, xfer);
  266.    pipe->transfer_destroy(pipe, xfer);
  267. }
  268.  
  269.  
  270. /**
  271.  * Copy the image at level=0 in 'src' to the 'dst' resource at 'dstLevel'.
  272.  * This is used to copy mipmap images from one texture buffer to another.
  273.  * This typically happens when our initial guess at the total texture size
  274.  * is incorrect (see the guess_and_alloc_texture() function).
  275.  */
  276. void
  277. st_texture_image_copy(struct pipe_context *pipe,
  278.                       struct pipe_resource *dst, GLuint dstLevel,
  279.                       struct pipe_resource *src, GLuint srcLevel,
  280.                       GLuint face)
  281. {
  282.    GLuint width = u_minify(dst->width0, dstLevel);
  283.    GLuint height = u_minify(dst->height0, dstLevel);
  284.    GLuint depth = u_minify(dst->depth0, dstLevel);
  285.    struct pipe_box src_box;
  286.    GLuint i;
  287.  
  288.    assert(u_minify(src->width0, srcLevel) == width);
  289.    assert(u_minify(src->height0, srcLevel) == height);
  290.    assert(u_minify(src->depth0, srcLevel) == depth);
  291.  
  292.    src_box.x = 0;
  293.    src_box.y = 0;
  294.    src_box.width = width;
  295.    src_box.height = height;
  296.    src_box.depth = 1;
  297.    /* Loop over 3D image slices */
  298.    /* could (and probably should) use "true" 3d box here -
  299.       but drivers can't quite handle it yet */
  300.    for (i = face; i < face + depth; i++) {
  301.       src_box.z = i;
  302.  
  303.       if (0)  {
  304.          print_center_pixel(pipe, src);
  305.       }
  306.  
  307.       pipe->resource_copy_region(pipe,
  308.                                  dst,
  309.                                  dstLevel,
  310.                                  0, 0, i,/* destX, Y, Z */
  311.                                  src,
  312.                                  srcLevel,
  313.                                  &src_box);
  314.    }
  315. }
  316.  
  317.