Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | 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 "main/image.h"
  29. #include "main/pbo.h"
  30. #include "main/imports.h"
  31. #include "main/readpix.h"
  32. #include "main/enums.h"
  33. #include "main/framebuffer.h"
  34. #include "util/u_inlines.h"
  35. #include "util/u_format.h"
  36.  
  37. #include "st_cb_fbo.h"
  38. #include "st_atom.h"
  39. #include "st_context.h"
  40. #include "st_cb_bitmap.h"
  41. #include "st_cb_readpixels.h"
  42. #include "state_tracker/st_cb_texture.h"
  43. #include "state_tracker/st_format.h"
  44. #include "state_tracker/st_texture.h"
  45.  
  46.  
  47. /**
  48.  * This uses a blit to copy the read buffer to a texture format which matches
  49.  * the format and type combo and then a fast read-back is done using memcpy.
  50.  * We can do arbitrary X/Y/Z/W/0/1 swizzling here as long as there is
  51.  * a format which matches the swizzling.
  52.  *
  53.  * If such a format isn't available, we fall back to _mesa_readpixels.
  54.  *
  55.  * NOTE: Some drivers use a blit to convert between tiled and linear
  56.  *       texture layouts during texture uploads/downloads, so the blit
  57.  *       we do here should be free in such cases.
  58.  */
  59. static void
  60. st_readpixels(struct gl_context *ctx, GLint x, GLint y,
  61.               GLsizei width, GLsizei height,
  62.               GLenum format, GLenum type,
  63.               const struct gl_pixelstore_attrib *pack,
  64.               GLvoid *pixels)
  65. {
  66.    struct st_context *st = st_context(ctx);
  67.    struct gl_renderbuffer *rb =
  68.          _mesa_get_read_renderbuffer_for_format(ctx, format);
  69.    struct st_renderbuffer *strb = st_renderbuffer(rb);
  70.    struct pipe_context *pipe = st->pipe;
  71.    struct pipe_screen *screen = pipe->screen;
  72.    struct pipe_resource *src;
  73.    struct pipe_resource *dst = NULL;
  74.    struct pipe_resource dst_templ;
  75.    enum pipe_format dst_format, src_format;
  76.    struct pipe_blit_info blit;
  77.    unsigned bind = PIPE_BIND_TRANSFER_READ;
  78.    struct pipe_transfer *tex_xfer;
  79.    ubyte *map = NULL;
  80.  
  81.    /* Validate state (to be sure we have up-to-date framebuffer surfaces)
  82.     * and flush the bitmap cache prior to reading. */
  83.    st_validate_state(st);
  84.    st_flush_bitmap_cache(st);
  85.  
  86.    if (!st->prefer_blit_based_texture_transfer) {
  87.       goto fallback;
  88.    }
  89.  
  90.    /* This must be done after state validation. */
  91.    src = strb->texture;
  92.  
  93.    /* XXX Fallback for depth-stencil formats due to an incomplete
  94.     * stencil blit implementation in some drivers. */
  95.    if (format == GL_DEPTH_STENCIL) {
  96.       goto fallback;
  97.    }
  98.  
  99.    /* We are creating a texture of the size of the region being read back.
  100.     * Need to check for NPOT texture support. */
  101.    if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES) &&
  102.        (!util_is_power_of_two(width) ||
  103.         !util_is_power_of_two(height))) {
  104.       goto fallback;
  105.    }
  106.  
  107.    /* If the base internal format and the texture format don't match, we have
  108.     * to use the slow path. */
  109.    if (rb->_BaseFormat !=
  110.        _mesa_get_format_base_format(rb->Format)) {
  111.       goto fallback;
  112.    }
  113.  
  114.    /* See if the texture format already matches the format and type,
  115.     * in which case the memcpy-based fast path will likely be used and
  116.     * we don't have to blit. */
  117.    if (_mesa_format_matches_format_and_type(rb->Format, format,
  118.                                             type, pack->SwapBytes)) {
  119.       goto fallback;
  120.    }
  121.  
  122.    if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_TRUE)) {
  123.       goto fallback;
  124.    }
  125.  
  126.    /* Convert the source format to what is expected by ReadPixels
  127.     * and see if it's supported. */
  128.    src_format = util_format_linear(src->format);
  129.    src_format = util_format_luminance_to_red(src_format);
  130.    src_format = util_format_intensity_to_red(src_format);
  131.  
  132.    if (!src_format ||
  133.        !screen->is_format_supported(screen, src_format, src->target,
  134.                                     src->nr_samples,
  135.                                     PIPE_BIND_SAMPLER_VIEW)) {
  136.       goto fallback;
  137.    }
  138.  
  139.    if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL)
  140.       bind |= PIPE_BIND_DEPTH_STENCIL;
  141.    else
  142.       bind |= PIPE_BIND_RENDER_TARGET;
  143.  
  144.    /* Choose the destination format by finding the best match
  145.     * for the format+type combo. */
  146.    dst_format = st_choose_matching_format(screen, bind, format, type,
  147.                                           pack->SwapBytes);
  148.    if (dst_format == PIPE_FORMAT_NONE) {
  149.       goto fallback;
  150.    }
  151.  
  152.    /* create the destination texture */
  153.    memset(&dst_templ, 0, sizeof(dst_templ));
  154.    dst_templ.target = PIPE_TEXTURE_2D;
  155.    dst_templ.format = dst_format;
  156.    dst_templ.bind = bind;
  157.    dst_templ.usage = PIPE_USAGE_STAGING;
  158.  
  159.    st_gl_texture_dims_to_pipe_dims(GL_TEXTURE_2D, width, height, 1,
  160.                                    &dst_templ.width0, &dst_templ.height0,
  161.                                    &dst_templ.depth0, &dst_templ.array_size);
  162.  
  163.    dst = screen->resource_create(screen, &dst_templ);
  164.    if (!dst) {
  165.       goto fallback;
  166.    }
  167.  
  168.    blit.src.resource = src;
  169.    blit.src.level = strb->rtt_level;
  170.    blit.src.format = src_format;
  171.    blit.dst.resource = dst;
  172.    blit.dst.level = 0;
  173.    blit.dst.format = dst->format;
  174.    blit.src.box.x = x;
  175.    blit.dst.box.x = 0;
  176.    blit.src.box.y = y;
  177.    blit.dst.box.y = 0;
  178.    blit.src.box.z = strb->rtt_face + strb->rtt_slice;
  179.    blit.dst.box.z = 0;
  180.    blit.src.box.width = blit.dst.box.width = width;
  181.    blit.src.box.height = blit.dst.box.height = height;
  182.    blit.src.box.depth = blit.dst.box.depth = 1;
  183.    blit.mask = st_get_blit_mask(rb->_BaseFormat, format);
  184.    blit.filter = PIPE_TEX_FILTER_NEAREST;
  185.    blit.scissor_enable = FALSE;
  186.  
  187.    if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
  188.       blit.src.box.y = rb->Height - blit.src.box.y;
  189.       blit.src.box.height = -blit.src.box.height;
  190.    }
  191.  
  192.    /* blit */
  193.    st->pipe->blit(st->pipe, &blit);
  194.  
  195.    /* map resources */
  196.    pixels = _mesa_map_pbo_dest(ctx, pack, pixels);
  197.  
  198.    map = pipe_transfer_map_3d(pipe, dst, 0, PIPE_TRANSFER_READ,
  199.                               0, 0, 0, width, height, 1, &tex_xfer);
  200.    if (!map) {
  201.       _mesa_unmap_pbo_dest(ctx, pack);
  202.       pipe_resource_reference(&dst, NULL);
  203.       goto fallback;
  204.    }
  205.  
  206.    /* memcpy data into a user buffer */
  207.    {
  208.       const uint bytesPerRow = width * util_format_get_blocksize(dst_format);
  209.       GLuint row;
  210.  
  211.       for (row = 0; row < (unsigned) height; row++) {
  212.          GLvoid *dest = _mesa_image_address3d(pack, pixels,
  213.                                               width, height, format,
  214.                                               type, 0, row, 0);
  215.          memcpy(dest, map, bytesPerRow);
  216.          map += tex_xfer->stride;
  217.       }
  218.    }
  219.  
  220.    pipe_transfer_unmap(pipe, tex_xfer);
  221.    _mesa_unmap_pbo_dest(ctx, pack);
  222.    pipe_resource_reference(&dst, NULL);
  223.    return;
  224.  
  225. fallback:
  226.    _mesa_readpixels(ctx, x, y, width, height, format, type, pack, pixels);
  227. }
  228.  
  229. void st_init_readpixels_functions(struct dd_function_table *functions)
  230. {
  231.    functions->ReadPixels = st_readpixels;
  232. }
  233.