Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 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. #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. #include "util/u_memory.h"
  44.  
  45.  
  46. #define DBG if(0) printf
  47.  
  48.  
  49. /**
  50.  * Allocate a new pipe_resource object
  51.  * width0, height0, depth0 are the dimensions of the level 0 image
  52.  * (the highest resolution).  last_level indicates how many mipmap levels
  53.  * to allocate storage for.  For non-mipmapped textures, this will be zero.
  54.  */
  55. struct pipe_resource *
  56. st_texture_create(struct st_context *st,
  57.                   enum pipe_texture_target target,
  58.                   enum pipe_format format,
  59.                   GLuint last_level,
  60.                   GLuint width0,
  61.                   GLuint height0,
  62.                   GLuint depth0,
  63.                   GLuint layers,
  64.                   GLuint nr_samples,
  65.                   GLuint bind )
  66. {
  67.    struct pipe_resource pt, *newtex;
  68.    struct pipe_screen *screen = st->pipe->screen;
  69.  
  70.    assert(target < PIPE_MAX_TEXTURE_TYPES);
  71.    assert(width0 > 0);
  72.    assert(height0 > 0);
  73.    assert(depth0 > 0);
  74.    if (target == PIPE_TEXTURE_CUBE)
  75.       assert(layers == 6);
  76.  
  77.    DBG("%s target %d format %s last_level %d\n", __func__,
  78.        (int) target, util_format_name(format), last_level);
  79.  
  80.    assert(format);
  81.    assert(screen->is_format_supported(screen, format, target, 0,
  82.                                       PIPE_BIND_SAMPLER_VIEW));
  83.  
  84.    memset(&pt, 0, sizeof(pt));
  85.    pt.target = target;
  86.    pt.format = format;
  87.    pt.last_level = last_level;
  88.    pt.width0 = width0;
  89.    pt.height0 = height0;
  90.    pt.depth0 = depth0;
  91.    pt.array_size = layers;
  92.    pt.usage = PIPE_USAGE_DEFAULT;
  93.    pt.bind = bind;
  94.    pt.flags = 0;
  95.    pt.nr_samples = nr_samples;
  96.  
  97.    newtex = screen->resource_create(screen, &pt);
  98.  
  99.    assert(!newtex || pipe_is_referenced(&newtex->reference));
  100.  
  101.    return newtex;
  102. }
  103.  
  104.  
  105. /**
  106.  * In OpenGL the number of 1D array texture layers is the "height" and
  107.  * the number of 2D array texture layers is the "depth".  In Gallium the
  108.  * number of layers in an array texture is a separate 'array_size' field.
  109.  * This function converts dimensions from the former to the later.
  110.  */
  111. void
  112. st_gl_texture_dims_to_pipe_dims(GLenum texture,
  113.                                 GLuint widthIn,
  114.                                 GLuint heightIn,
  115.                                 GLuint depthIn,
  116.                                 GLuint *widthOut,
  117.                                 GLuint *heightOut,
  118.                                 GLuint *depthOut,
  119.                                 GLuint *layersOut)
  120. {
  121.    switch (texture) {
  122.    case GL_TEXTURE_1D:
  123.    case GL_PROXY_TEXTURE_1D:
  124.       assert(heightIn == 1);
  125.       assert(depthIn == 1);
  126.       *widthOut = widthIn;
  127.       *heightOut = 1;
  128.       *depthOut = 1;
  129.       *layersOut = 1;
  130.       break;
  131.    case GL_TEXTURE_1D_ARRAY:
  132.    case GL_PROXY_TEXTURE_1D_ARRAY:
  133.       assert(depthIn == 1);
  134.       *widthOut = widthIn;
  135.       *heightOut = 1;
  136.       *depthOut = 1;
  137.       *layersOut = heightIn;
  138.       break;
  139.    case GL_TEXTURE_2D:
  140.    case GL_PROXY_TEXTURE_2D:
  141.    case GL_TEXTURE_RECTANGLE:
  142.    case GL_PROXY_TEXTURE_RECTANGLE:
  143.    case GL_TEXTURE_EXTERNAL_OES:
  144.    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
  145.    case GL_TEXTURE_2D_MULTISAMPLE:
  146.       assert(depthIn == 1);
  147.       *widthOut = widthIn;
  148.       *heightOut = heightIn;
  149.       *depthOut = 1;
  150.       *layersOut = 1;
  151.       break;
  152.    case GL_TEXTURE_CUBE_MAP:
  153.    case GL_PROXY_TEXTURE_CUBE_MAP:
  154.    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
  155.    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
  156.    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
  157.    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
  158.    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
  159.    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
  160.       assert(depthIn == 1);
  161.       *widthOut = widthIn;
  162.       *heightOut = heightIn;
  163.       *depthOut = 1;
  164.       *layersOut = 6;
  165.       break;
  166.    case GL_TEXTURE_2D_ARRAY:
  167.    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
  168.    case GL_PROXY_TEXTURE_2D_ARRAY:
  169.    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
  170.       *widthOut = widthIn;
  171.       *heightOut = heightIn;
  172.       *depthOut = 1;
  173.       *layersOut = depthIn;
  174.       break;
  175.    case GL_TEXTURE_CUBE_MAP_ARRAY:
  176.    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
  177.       *widthOut = widthIn;
  178.       *heightOut = heightIn;
  179.       *depthOut = 1;
  180.       *layersOut = util_align_npot(depthIn, 6);
  181.       break;
  182.    default:
  183.       assert(0 && "Unexpected texture in st_gl_texture_dims_to_pipe_dims()");
  184.       /* fall-through */
  185.    case GL_TEXTURE_3D:
  186.    case GL_PROXY_TEXTURE_3D:
  187.       *widthOut = widthIn;
  188.       *heightOut = heightIn;
  189.       *depthOut = depthIn;
  190.       *layersOut = 1;
  191.       break;
  192.    }
  193. }
  194.  
  195.  
  196. /**
  197.  * Check if a texture image can be pulled into a unified mipmap texture.
  198.  */
  199. GLboolean
  200. st_texture_match_image(struct st_context *st,
  201.                        const struct pipe_resource *pt,
  202.                        const struct gl_texture_image *image)
  203. {
  204.    GLuint ptWidth, ptHeight, ptDepth, ptLayers;
  205.  
  206.    /* Images with borders are never pulled into mipmap textures.
  207.     */
  208.    if (image->Border)
  209.       return GL_FALSE;
  210.  
  211.    /* Check if this image's format matches the established texture's format.
  212.     */
  213.    if (st_mesa_format_to_pipe_format(st, image->TexFormat) != pt->format)
  214.       return GL_FALSE;
  215.  
  216.    st_gl_texture_dims_to_pipe_dims(image->TexObject->Target,
  217.                                    image->Width, image->Height, image->Depth,
  218.                                    &ptWidth, &ptHeight, &ptDepth, &ptLayers);
  219.  
  220.    /* Test if this image's size matches what's expected in the
  221.     * established texture.
  222.     */
  223.    if (ptWidth != u_minify(pt->width0, image->Level) ||
  224.        ptHeight != u_minify(pt->height0, image->Level) ||
  225.        ptDepth != u_minify(pt->depth0, image->Level) ||
  226.        ptLayers != pt->array_size)
  227.       return GL_FALSE;
  228.  
  229.    return GL_TRUE;
  230. }
  231.  
  232.  
  233. /**
  234.  * Map a texture image and return the address for a particular 2D face/slice/
  235.  * layer.  The stImage indicates the cube face and mipmap level.  The slice
  236.  * of the 3D texture is passed in 'zoffset'.
  237.  * \param usage  one of the PIPE_TRANSFER_x values
  238.  * \param x, y, w, h  the region of interest of the 2D image.
  239.  * \return address of mapping or NULL if any error
  240.  */
  241. GLubyte *
  242. st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
  243.                      enum pipe_transfer_usage usage,
  244.                      GLuint x, GLuint y, GLuint z,
  245.                      GLuint w, GLuint h, GLuint d,
  246.                      struct pipe_transfer **transfer)
  247. {
  248.    struct st_texture_object *stObj =
  249.       st_texture_object(stImage->base.TexObject);
  250.    GLuint level;
  251.    void *map;
  252.  
  253.    DBG("%s \n", __func__);
  254.  
  255.    if (!stImage->pt)
  256.       return NULL;
  257.  
  258.    if (stObj->pt != stImage->pt)
  259.       level = 0;
  260.    else
  261.       level = stImage->base.Level;
  262.  
  263.    if (stObj->base.Immutable) {
  264.       level += stObj->base.MinLevel;
  265.       z += stObj->base.MinLayer;
  266.       if (stObj->pt->array_size > 1)
  267.          d = MIN2(d, stObj->base.NumLayers);
  268.    }
  269.  
  270.    z += stImage->base.Face;
  271.  
  272.    map = pipe_transfer_map_3d(st->pipe, stImage->pt, level, usage,
  273.                               x, y, z, w, h, d, transfer);
  274.    if (map) {
  275.       /* Enlarge the transfer array if it's not large enough. */
  276.       if (z >= stImage->num_transfers) {
  277.          unsigned new_size = z + 1;
  278.  
  279.          stImage->transfer = realloc(stImage->transfer,
  280.                      new_size * sizeof(struct st_texture_image_transfer));
  281.          memset(&stImage->transfer[stImage->num_transfers], 0,
  282.                 (new_size - stImage->num_transfers) *
  283.                 sizeof(struct st_texture_image_transfer));
  284.          stImage->num_transfers = new_size;
  285.       }
  286.  
  287.       assert(!stImage->transfer[z].transfer);
  288.       stImage->transfer[z].transfer = *transfer;
  289.    }
  290.    return map;
  291. }
  292.  
  293.  
  294. void
  295. st_texture_image_unmap(struct st_context *st,
  296.                        struct st_texture_image *stImage, unsigned slice)
  297. {
  298.    struct pipe_context *pipe = st->pipe;
  299.    struct st_texture_object *stObj =
  300.       st_texture_object(stImage->base.TexObject);
  301.    struct pipe_transfer **transfer;
  302.  
  303.    if (stObj->base.Immutable)
  304.       slice += stObj->base.MinLayer;
  305.    transfer = &stImage->transfer[slice + stImage->base.Face].transfer;
  306.  
  307.    DBG("%s\n", __func__);
  308.  
  309.    pipe_transfer_unmap(pipe, *transfer);
  310.    *transfer = NULL;
  311. }
  312.  
  313. /**
  314.  * For debug only: get/print center pixel in the src resource.
  315.  */
  316. static void
  317. print_center_pixel(struct pipe_context *pipe, struct pipe_resource *src)
  318. {
  319.    struct pipe_transfer *xfer;
  320.    struct pipe_box region;
  321.    ubyte *map;
  322.  
  323.    region.x = src->width0 / 2;
  324.    region.y = src->height0 / 2;
  325.    region.z = 0;
  326.    region.width = 1;
  327.    region.height = 1;
  328.    region.depth = 1;
  329.  
  330.    map = pipe->transfer_map(pipe, src, 0, PIPE_TRANSFER_READ, &region, &xfer);
  331.  
  332.    printf("center pixel: %d %d %d %d\n", map[0], map[1], map[2], map[3]);
  333.  
  334.    pipe->transfer_unmap(pipe, xfer);
  335. }
  336.  
  337.  
  338. /**
  339.  * Copy the image at level=0 in 'src' to the 'dst' resource at 'dstLevel'.
  340.  * This is used to copy mipmap images from one texture buffer to another.
  341.  * This typically happens when our initial guess at the total texture size
  342.  * is incorrect (see the guess_and_alloc_texture() function).
  343.  */
  344. void
  345. st_texture_image_copy(struct pipe_context *pipe,
  346.                       struct pipe_resource *dst, GLuint dstLevel,
  347.                       struct pipe_resource *src, GLuint srcLevel,
  348.                       GLuint face)
  349. {
  350.    GLuint width = u_minify(dst->width0, dstLevel);
  351.    GLuint height = u_minify(dst->height0, dstLevel);
  352.    GLuint depth = u_minify(dst->depth0, dstLevel);
  353.    struct pipe_box src_box;
  354.    GLuint i;
  355.  
  356.    if (u_minify(src->width0, srcLevel) != width ||
  357.        u_minify(src->height0, srcLevel) != height ||
  358.        u_minify(src->depth0, srcLevel) != depth) {
  359.       /* The source image size doesn't match the destination image size.
  360.        * This can happen in some degenerate situations such as rendering to a
  361.        * cube map face which was set up with mismatched texture sizes.
  362.        */
  363.       return;
  364.    }
  365.  
  366.    src_box.x = 0;
  367.    src_box.y = 0;
  368.    src_box.width = width;
  369.    src_box.height = height;
  370.    src_box.depth = 1;
  371.  
  372.    if (src->target == PIPE_TEXTURE_1D_ARRAY ||
  373.        src->target == PIPE_TEXTURE_2D_ARRAY ||
  374.        src->target == PIPE_TEXTURE_CUBE_ARRAY) {
  375.       face = 0;
  376.       depth = src->array_size;
  377.    }
  378.  
  379.    /* Loop over 3D image slices */
  380.    /* could (and probably should) use "true" 3d box here -
  381.       but drivers can't quite handle it yet */
  382.    for (i = face; i < face + depth; i++) {
  383.       src_box.z = i;
  384.  
  385.       if (0)  {
  386.          print_center_pixel(pipe, src);
  387.       }
  388.  
  389.       pipe->resource_copy_region(pipe,
  390.                                  dst,
  391.                                  dstLevel,
  392.                                  0, 0, i,/* destX, Y, Z */
  393.                                  src,
  394.                                  srcLevel,
  395.                                  &src_box);
  396.    }
  397. }
  398.  
  399.  
  400. struct pipe_resource *
  401. st_create_color_map_texture(struct gl_context *ctx)
  402. {
  403.    struct st_context *st = st_context(ctx);
  404.    struct pipe_resource *pt;
  405.    enum pipe_format format;
  406.    const uint texSize = 256; /* simple, and usually perfect */
  407.  
  408.    /* find an RGBA texture format */
  409.    format = st_choose_format(st, GL_RGBA, GL_NONE, GL_NONE,
  410.                              PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW,
  411.                              FALSE);
  412.  
  413.    /* create texture for color map/table */
  414.    pt = st_texture_create(st, PIPE_TEXTURE_2D, format, 0,
  415.                           texSize, texSize, 1, 1, 0, PIPE_BIND_SAMPLER_VIEW);
  416.    return pt;
  417. }
  418.  
  419. /**
  420.  * Try to find a matching sampler view for the given context.
  421.  * If none is found an empty slot is initialized with a
  422.  * template and returned instead.
  423.  */
  424. struct pipe_sampler_view **
  425. st_texture_get_sampler_view(struct st_context *st,
  426.                             struct st_texture_object *stObj)
  427. {
  428.    struct pipe_sampler_view *used = NULL, **free = NULL;
  429.    GLuint i;
  430.  
  431.    for (i = 0; i < stObj->num_sampler_views; ++i) {
  432.       struct pipe_sampler_view **sv = &stObj->sampler_views[i];
  433.       /* Is the array entry used ? */
  434.       if (*sv) {
  435.          /* Yes, check if it's the right one */
  436.          if ((*sv)->context == st->pipe)
  437.             return sv;
  438.  
  439.          /* Wasn't the right one, but remember it as template */
  440.          used = *sv;
  441.       } else {
  442.          /* Found a free slot, remember that */
  443.          free = sv;
  444.       }
  445.    }
  446.  
  447.    /* Couldn't find a slot for our context, create a new one */
  448.  
  449.    if (!free) {
  450.       /* Haven't even found a free one, resize the array */
  451.       GLuint old_size = stObj->num_sampler_views * sizeof(void *);
  452.       GLuint new_size = old_size + sizeof(void *);
  453.       stObj->sampler_views = REALLOC(stObj->sampler_views, old_size, new_size);
  454.       free = &stObj->sampler_views[stObj->num_sampler_views++];
  455.       *free = NULL;
  456.    }
  457.  
  458.    /* Add just any sampler view to be used as a template */
  459.    if (used)
  460.       pipe_sampler_view_reference(free, used);
  461.  
  462.    return free;
  463. }
  464.  
  465. void
  466. st_texture_release_sampler_view(struct st_context *st,
  467.                                 struct st_texture_object *stObj)
  468. {
  469.    GLuint i;
  470.  
  471.    for (i = 0; i < stObj->num_sampler_views; ++i) {
  472.       struct pipe_sampler_view **sv = &stObj->sampler_views[i];
  473.  
  474.       if (*sv && (*sv)->context == st->pipe) {
  475.          pipe_sampler_view_reference(sv, NULL);
  476.          break;
  477.       }
  478.    }
  479. }
  480.  
  481. void
  482. st_texture_release_all_sampler_views(struct st_context *st,
  483.                                      struct st_texture_object *stObj)
  484. {
  485.    GLuint i;
  486.  
  487.    /* XXX This should use sampler_views[i]->pipe, not st->pipe */
  488.    for (i = 0; i < stObj->num_sampler_views; ++i)
  489.       pipe_sampler_view_release(st->pipe, &stObj->sampler_views[i]);
  490. }
  491.  
  492.  
  493. void
  494. st_texture_free_sampler_views(struct st_texture_object *stObj)
  495. {
  496.    /* NOTE:
  497.     * We use FREE() here to match REALLOC() above.  Both come from
  498.     * u_memory.h, not imports.h.  If we mis-match MALLOC/FREE from
  499.     * those two headers we can trash the heap.
  500.     */
  501.    FREE(stObj->sampler_views);
  502. }
  503.