Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 2015 Intel Corporation.  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.  * Authors:
  25.  *    Jason Ekstrand <jason.ekstrand@intel.com>
  26.  */
  27.  
  28. #include "bufferobj.h"
  29. #include "buffers.h"
  30. #include "fbobject.h"
  31. #include "glformats.h"
  32. #include "glheader.h"
  33. #include "image.h"
  34. #include "macros.h"
  35. #include "meta.h"
  36. #include "pbo.h"
  37. #include "shaderapi.h"
  38. #include "state.h"
  39. #include "teximage.h"
  40. #include "texobj.h"
  41. #include "texstate.h"
  42. #include "uniforms.h"
  43. #include "varray.h"
  44.  
  45. static struct gl_texture_image *
  46. create_texture_for_pbo(struct gl_context *ctx, bool create_pbo,
  47.                        GLenum pbo_target, int width, int height,
  48.                        GLenum format, GLenum type, const void *pixels,
  49.                        const struct gl_pixelstore_attrib *packing,
  50.                        GLuint *tmp_pbo, GLuint *tmp_tex)
  51. {
  52.    uint32_t pbo_format;
  53.    GLenum internal_format;
  54.    unsigned row_stride;
  55.    struct gl_buffer_object *buffer_obj;
  56.    struct gl_texture_object *tex_obj;
  57.    struct gl_texture_image *tex_image;
  58.    bool read_only;
  59.  
  60.    if (packing->SwapBytes ||
  61.        packing->LsbFirst ||
  62.        packing->Invert)
  63.       return NULL;
  64.  
  65.    pbo_format = _mesa_format_from_format_and_type(format, type);
  66.    if (_mesa_format_is_mesa_array_format(pbo_format))
  67.       pbo_format = _mesa_format_from_array_format(pbo_format);
  68.  
  69.    if (!pbo_format || !ctx->TextureFormatSupported[pbo_format])
  70.       return NULL;
  71.  
  72.    /* Account for SKIP_PIXELS, SKIP_ROWS, ALIGNMENT, and SKIP_IMAGES */
  73.    pixels = _mesa_image_address3d(packing, pixels,
  74.                                   width, height, format, type, 0, 0, 0);
  75.    row_stride = _mesa_image_row_stride(packing, width, format, type);
  76.  
  77.    if (_mesa_is_bufferobj(packing->BufferObj)) {
  78.       *tmp_pbo = 0;
  79.       buffer_obj = packing->BufferObj;
  80.    } else {
  81.       bool is_pixel_pack = pbo_target == GL_PIXEL_PACK_BUFFER;
  82.  
  83.       assert(create_pbo);
  84.  
  85.       _mesa_GenBuffers(1, tmp_pbo);
  86.  
  87.       /* We are not doing this inside meta_begin/end.  However, we know the
  88.        * client doesn't have the given target bound, so we can go ahead and
  89.        * squash it.  We'll set it back when we're done.
  90.        */
  91.       _mesa_BindBuffer(pbo_target, *tmp_pbo);
  92.  
  93.       /* In case of GL_PIXEL_PACK_BUFFER, pass null pointer for the pixel
  94.        * data to avoid unnecessary data copying in _mesa_BufferData().
  95.        */
  96.       if (is_pixel_pack)
  97.          _mesa_BufferData(pbo_target, row_stride * height, NULL,
  98.                           GL_STREAM_READ);
  99.       else
  100.          _mesa_BufferData(pbo_target, row_stride * height, pixels,
  101.                           GL_STREAM_DRAW);
  102.  
  103.       buffer_obj = packing->BufferObj;
  104.       pixels = NULL;
  105.  
  106.       _mesa_BindBuffer(pbo_target, 0);
  107.    }
  108.  
  109.    _mesa_GenTextures(1, tmp_tex);
  110.    tex_obj = _mesa_lookup_texture(ctx, *tmp_tex);
  111.    _mesa_initialize_texture_object(ctx, tex_obj, *tmp_tex, GL_TEXTURE_2D);
  112.    /* This must be set after _mesa_initialize_texture_object, not before. */
  113.    tex_obj->Immutable = GL_TRUE;
  114.    /* This is required for interactions with ARB_texture_view. */
  115.    tex_obj->NumLayers = 1;
  116.  
  117.    internal_format = _mesa_get_format_base_format(pbo_format);
  118.  
  119.    tex_image = _mesa_get_tex_image(ctx, tex_obj, tex_obj->Target, 0);
  120.    _mesa_init_teximage_fields(ctx, tex_image, width, height, 1,
  121.                               0, internal_format, pbo_format);
  122.  
  123.    read_only = pbo_target == GL_PIXEL_UNPACK_BUFFER;
  124.    if (!ctx->Driver.SetTextureStorageForBufferObject(ctx, tex_obj,
  125.                                                      buffer_obj,
  126.                                                      (intptr_t)pixels,
  127.                                                      row_stride,
  128.                                                      read_only)) {
  129.       _mesa_DeleteTextures(1, tmp_tex);
  130.       _mesa_DeleteBuffers(1, tmp_pbo);
  131.       return NULL;
  132.    }
  133.  
  134.    return tex_image;
  135. }
  136.  
  137. bool
  138. _mesa_meta_pbo_TexSubImage(struct gl_context *ctx, GLuint dims,
  139.                            struct gl_texture_image *tex_image,
  140.                            int xoffset, int yoffset, int zoffset,
  141.                            int width, int height, int depth,
  142.                            GLenum format, GLenum type, const void *pixels,
  143.                            bool allocate_storage, bool create_pbo,
  144.                            const struct gl_pixelstore_attrib *packing)
  145. {
  146.    GLuint pbo = 0, pbo_tex = 0, fbos[2] = { 0, 0 };
  147.    int full_height, image_height;
  148.    struct gl_texture_image *pbo_tex_image;
  149.    GLenum status;
  150.    bool success = false;
  151.    int z;
  152.  
  153.    if (!_mesa_is_bufferobj(packing->BufferObj) && !create_pbo)
  154.       return false;
  155.  
  156.    if (format == GL_DEPTH_COMPONENT ||
  157.        format == GL_DEPTH_STENCIL ||
  158.        format == GL_STENCIL_INDEX ||
  159.        format == GL_COLOR_INDEX)
  160.       return false;
  161.  
  162.    if (ctx->_ImageTransferState)
  163.       return false;
  164.  
  165.    /* For arrays, use a tall (height * depth) 2D texture but taking into
  166.     * account the inter-image padding specified with the image height packing
  167.     * property.
  168.     */
  169.    image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight;
  170.    full_height = image_height * (depth - 1) + height;
  171.  
  172.    pbo_tex_image = create_texture_for_pbo(ctx, create_pbo,
  173.                                           GL_PIXEL_UNPACK_BUFFER,
  174.                                           width, full_height,
  175.                                           format, type, pixels, packing,
  176.                                           &pbo, &pbo_tex);
  177.    if (!pbo_tex_image)
  178.       return false;
  179.  
  180.    if (allocate_storage)
  181.       ctx->Driver.AllocTextureImageBuffer(ctx, tex_image);
  182.  
  183.    _mesa_meta_begin(ctx, ~(MESA_META_PIXEL_TRANSFER |
  184.                            MESA_META_PIXEL_STORE));
  185.  
  186.    _mesa_GenFramebuffers(2, fbos);
  187.    _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]);
  188.    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
  189.  
  190.    if (tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
  191.       assert(depth == 1);
  192.       assert(zoffset == 0);
  193.       depth = height;
  194.       height = 1;
  195.       image_height = 1;
  196.       zoffset = yoffset;
  197.       yoffset = 0;
  198.    }
  199.  
  200.    _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  201.                              pbo_tex_image, 0);
  202.    /* If this passes on the first layer it should pass on the others */
  203.    status = _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER);
  204.    if (status != GL_FRAMEBUFFER_COMPLETE)
  205.       goto fail;
  206.  
  207.    _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  208.                              tex_image, zoffset);
  209.    /* If this passes on the first layer it should pass on the others */
  210.    status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
  211.    if (status != GL_FRAMEBUFFER_COMPLETE)
  212.       goto fail;
  213.  
  214.    _mesa_update_state(ctx);
  215.  
  216.    if (_mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
  217.                                   0, 0, width, height,
  218.                                   xoffset, yoffset,
  219.                                   xoffset + width, yoffset + height,
  220.                                   GL_COLOR_BUFFER_BIT, GL_NEAREST))
  221.       goto fail;
  222.  
  223.    for (z = 1; z < depth; z++) {
  224.       _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  225.                                 tex_image, zoffset + z);
  226.  
  227.       _mesa_update_state(ctx);
  228.  
  229.       _mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
  230.                                  0, z * image_height,
  231.                                  width, z * image_height + height,
  232.                                  xoffset, yoffset,
  233.                                  xoffset + width, yoffset + height,
  234.                                  GL_COLOR_BUFFER_BIT, GL_NEAREST);
  235.    }
  236.  
  237.    success = true;
  238.  
  239. fail:
  240.    _mesa_DeleteFramebuffers(2, fbos);
  241.    _mesa_DeleteTextures(1, &pbo_tex);
  242.    _mesa_DeleteBuffers(1, &pbo);
  243.  
  244.    _mesa_meta_end(ctx);
  245.  
  246.    return success;
  247. }
  248.  
  249. bool
  250. _mesa_meta_pbo_GetTexSubImage(struct gl_context *ctx, GLuint dims,
  251.                               struct gl_texture_image *tex_image,
  252.                               int xoffset, int yoffset, int zoffset,
  253.                               int width, int height, int depth,
  254.                               GLenum format, GLenum type, const void *pixels,
  255.                               const struct gl_pixelstore_attrib *packing)
  256. {
  257.    GLuint pbo = 0, pbo_tex = 0, fbos[2] = { 0, 0 };
  258.    int full_height, image_height;
  259.    struct gl_texture_image *pbo_tex_image;
  260.    GLenum status;
  261.    bool success = false;
  262.    int z;
  263.  
  264.    if (!_mesa_is_bufferobj(packing->BufferObj))
  265.       return false;
  266.  
  267.    if (format == GL_DEPTH_COMPONENT ||
  268.        format == GL_DEPTH_STENCIL ||
  269.        format == GL_STENCIL_INDEX ||
  270.        format == GL_COLOR_INDEX)
  271.       return false;
  272.  
  273.    if (ctx->_ImageTransferState)
  274.       return false;
  275.  
  276.    /* For arrays, use a tall (height * depth) 2D texture but taking into
  277.     * account the inter-image padding specified with the image height packing
  278.     * property.
  279.     */
  280.    image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight;
  281.    full_height = image_height * (depth - 1) + height;
  282.  
  283.    pbo_tex_image = create_texture_for_pbo(ctx, false, GL_PIXEL_PACK_BUFFER,
  284.                                           width, full_height * depth,
  285.                                           format, type, pixels, packing,
  286.                                           &pbo, &pbo_tex);
  287.    if (!pbo_tex_image)
  288.       return false;
  289.  
  290.    _mesa_meta_begin(ctx, ~(MESA_META_PIXEL_TRANSFER |
  291.                            MESA_META_PIXEL_STORE));
  292.  
  293.    _mesa_GenFramebuffers(2, fbos);
  294.  
  295.    if (tex_image && tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
  296.       assert(depth == 1);
  297.       assert(zoffset == 0);
  298.       depth = height;
  299.       height = 1;
  300.       image_height = 1;
  301.       zoffset = yoffset;
  302.       yoffset = 0;
  303.    }
  304.  
  305.    /* If we were given a texture, bind it to the read framebuffer.  If not,
  306.     * we're doing a ReadPixels and we should just use whatever framebuffer
  307.     * the client has bound.
  308.     */
  309.    if (tex_image) {
  310.       _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]);
  311.       _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  312.                                 tex_image, zoffset);
  313.       /* If this passes on the first layer it should pass on the others */
  314.       status = _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER);
  315.       if (status != GL_FRAMEBUFFER_COMPLETE)
  316.          goto fail;
  317.    } else {
  318.       assert(depth == 1);
  319.    }
  320.  
  321.    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
  322.    _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  323.                              pbo_tex_image, 0);
  324.    /* If this passes on the first layer it should pass on the others */
  325.    status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
  326.    if (status != GL_FRAMEBUFFER_COMPLETE)
  327.       goto fail;
  328.  
  329.    _mesa_update_state(ctx);
  330.  
  331.    if (_mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
  332.                                   xoffset, yoffset,
  333.                                   xoffset + width, yoffset + height,
  334.                                   0, 0, width, height,
  335.                                   GL_COLOR_BUFFER_BIT, GL_NEAREST))
  336.       goto fail;
  337.  
  338.    for (z = 1; z < depth; z++) {
  339.       _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  340.                                 tex_image, zoffset + z);
  341.  
  342.       _mesa_update_state(ctx);
  343.  
  344.       _mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
  345.                                  xoffset, yoffset,
  346.                                  xoffset + width, yoffset + height,
  347.                                  0, z * image_height,
  348.                                  width, z * image_height + height,
  349.                                  GL_COLOR_BUFFER_BIT, GL_NEAREST);
  350.    }
  351.  
  352.    success = true;
  353.  
  354. fail:
  355.    _mesa_DeleteFramebuffers(2, fbos);
  356.    _mesa_DeleteTextures(1, &pbo_tex);
  357.    _mesa_DeleteBuffers(1, &pbo);
  358.  
  359.    _mesa_meta_end(ctx);
  360.  
  361.    return success;
  362. }
  363.