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.  
  29. /**
  30.  * Functions for pixel buffer objects and vertex/element buffer objects.
  31.  */
  32.  
  33.  
  34. #include <inttypes.h>  /* for PRId64 macro */
  35.  
  36. #include "main/imports.h"
  37. #include "main/mtypes.h"
  38. #include "main/arrayobj.h"
  39. #include "main/bufferobj.h"
  40.  
  41. #include "st_context.h"
  42. #include "st_cb_bufferobjects.h"
  43. #include "st_debug.h"
  44.  
  45. #include "pipe/p_context.h"
  46. #include "pipe/p_defines.h"
  47. #include "util/u_inlines.h"
  48.  
  49.  
  50. /**
  51.  * There is some duplication between mesa's bufferobjects and our
  52.  * bufmgr buffers.  Both have an integer handle and a hashtable to
  53.  * lookup an opaque structure.  It would be nice if the handles and
  54.  * internal structure where somehow shared.
  55.  */
  56. static struct gl_buffer_object *
  57. st_bufferobj_alloc(struct gl_context *ctx, GLuint name)
  58. {
  59.    struct st_buffer_object *st_obj = ST_CALLOC_STRUCT(st_buffer_object);
  60.  
  61.    if (!st_obj)
  62.       return NULL;
  63.  
  64.    _mesa_initialize_buffer_object(ctx, &st_obj->Base, name);
  65.  
  66.    return &st_obj->Base;
  67. }
  68.  
  69.  
  70.  
  71. /**
  72.  * Deallocate/free a vertex/pixel buffer object.
  73.  * Called via glDeleteBuffersARB().
  74.  */
  75. static void
  76. st_bufferobj_free(struct gl_context *ctx, struct gl_buffer_object *obj)
  77. {
  78.    struct st_buffer_object *st_obj = st_buffer_object(obj);
  79.  
  80.    assert(obj->RefCount == 0);
  81.    _mesa_buffer_unmap_all_mappings(ctx, obj);
  82.  
  83.    if (st_obj->buffer)
  84.       pipe_resource_reference(&st_obj->buffer, NULL);
  85.  
  86.    free(st_obj->Base.Label);
  87.    free(st_obj);
  88. }
  89.  
  90.  
  91.  
  92. /**
  93.  * Replace data in a subrange of buffer object.  If the data range
  94.  * specified by size + offset extends beyond the end of the buffer or
  95.  * if data is NULL, no copy is performed.
  96.  * Called via glBufferSubDataARB().
  97.  */
  98. static void
  99. st_bufferobj_subdata(struct gl_context *ctx,
  100.                      GLintptrARB offset,
  101.                      GLsizeiptrARB size,
  102.                      const GLvoid * data, struct gl_buffer_object *obj)
  103. {
  104.    struct st_buffer_object *st_obj = st_buffer_object(obj);
  105.  
  106.    /* we may be called from VBO code, so double-check params here */
  107.    assert(offset >= 0);
  108.    assert(size >= 0);
  109.    assert(offset + size <= obj->Size);
  110.  
  111.    if (!size)
  112.       return;
  113.  
  114.    /*
  115.     * According to ARB_vertex_buffer_object specification, if data is null,
  116.     * then the contents of the buffer object's data store is undefined. We just
  117.     * ignore, and leave it unchanged.
  118.     */
  119.    if (!data)
  120.       return;
  121.  
  122.    if (!st_obj->buffer) {
  123.       /* we probably ran out of memory during buffer allocation */
  124.       return;
  125.    }
  126.  
  127.    /* Now that transfers are per-context, we don't have to figure out
  128.     * flushing here.  Usually drivers won't need to flush in this case
  129.     * even if the buffer is currently referenced by hardware - they
  130.     * just queue the upload as dma rather than mapping the underlying
  131.     * buffer directly.
  132.     */
  133.    pipe_buffer_write(st_context(ctx)->pipe,
  134.                      st_obj->buffer,
  135.                      offset, size, data);
  136. }
  137.  
  138.  
  139. /**
  140.  * Called via glGetBufferSubDataARB().
  141.  */
  142. static void
  143. st_bufferobj_get_subdata(struct gl_context *ctx,
  144.                          GLintptrARB offset,
  145.                          GLsizeiptrARB size,
  146.                          GLvoid * data, struct gl_buffer_object *obj)
  147. {
  148.    struct st_buffer_object *st_obj = st_buffer_object(obj);
  149.  
  150.    /* we may be called from VBO code, so double-check params here */
  151.    assert(offset >= 0);
  152.    assert(size >= 0);
  153.    assert(offset + size <= obj->Size);
  154.  
  155.    if (!size)
  156.       return;
  157.  
  158.    if (!st_obj->buffer) {
  159.       /* we probably ran out of memory during buffer allocation */
  160.       return;
  161.    }
  162.  
  163.    pipe_buffer_read(st_context(ctx)->pipe, st_obj->buffer,
  164.                     offset, size, data);
  165. }
  166.  
  167.  
  168. /**
  169.  * Allocate space for and store data in a buffer object.  Any data that was
  170.  * previously stored in the buffer object is lost.  If data is NULL,
  171.  * memory will be allocated, but no copy will occur.
  172.  * Called via ctx->Driver.BufferData().
  173.  * \return GL_TRUE for success, GL_FALSE if out of memory
  174.  */
  175. static GLboolean
  176. st_bufferobj_data(struct gl_context *ctx,
  177.                   GLenum target,
  178.                   GLsizeiptrARB size,
  179.                   const GLvoid * data,
  180.                   GLenum usage,
  181.                   GLbitfield storageFlags,
  182.                   struct gl_buffer_object *obj)
  183. {
  184.    struct st_context *st = st_context(ctx);
  185.    struct pipe_context *pipe = st->pipe;
  186.    struct st_buffer_object *st_obj = st_buffer_object(obj);
  187.    unsigned bind, pipe_usage, pipe_flags = 0;
  188.  
  189.    if (target != GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD &&
  190.        size && data && st_obj->buffer &&
  191.        st_obj->Base.Size == size &&
  192.        st_obj->Base.Usage == usage &&
  193.        st_obj->Base.StorageFlags == storageFlags) {
  194.       /* Just discard the old contents and write new data.
  195.        * This should be the same as creating a new buffer, but we avoid
  196.        * a lot of validation in Mesa.
  197.        */
  198.       struct pipe_box box;
  199.  
  200.       u_box_1d(0, size, &box);
  201.       pipe->transfer_inline_write(pipe, st_obj->buffer, 0,
  202.                                   PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
  203.                                   &box, data, 0, 0);
  204.       return GL_TRUE;
  205.    }
  206.  
  207.    st_obj->Base.Size = size;
  208.    st_obj->Base.Usage = usage;
  209.    st_obj->Base.StorageFlags = storageFlags;
  210.  
  211.    switch (target) {
  212.    case GL_PIXEL_PACK_BUFFER_ARB:
  213.    case GL_PIXEL_UNPACK_BUFFER_ARB:
  214.       bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
  215.       break;
  216.    case GL_ARRAY_BUFFER_ARB:
  217.       bind = PIPE_BIND_VERTEX_BUFFER;
  218.       break;
  219.    case GL_ELEMENT_ARRAY_BUFFER_ARB:
  220.       bind = PIPE_BIND_INDEX_BUFFER;
  221.       break;
  222.    case GL_TEXTURE_BUFFER:
  223.       bind = PIPE_BIND_SAMPLER_VIEW;
  224.       break;
  225.    case GL_TRANSFORM_FEEDBACK_BUFFER:
  226.       bind = PIPE_BIND_STREAM_OUTPUT;
  227.       break;
  228.    case GL_UNIFORM_BUFFER:
  229.       bind = PIPE_BIND_CONSTANT_BUFFER;
  230.       break;
  231.    case GL_DRAW_INDIRECT_BUFFER:
  232.       bind = PIPE_BIND_COMMAND_ARGS_BUFFER;
  233.       break;
  234.    default:
  235.       bind = 0;
  236.    }
  237.  
  238.    /* Set usage. */
  239.    if (st_obj->Base.Immutable) {
  240.       /* BufferStorage */
  241.       if (storageFlags & GL_CLIENT_STORAGE_BIT)
  242.          pipe_usage = PIPE_USAGE_STAGING;
  243.       else
  244.          pipe_usage = PIPE_USAGE_DEFAULT;
  245.    }
  246.    else {
  247.       /* BufferData */
  248.       switch (usage) {
  249.       case GL_STATIC_DRAW:
  250.       case GL_STATIC_COPY:
  251.       default:
  252.          pipe_usage = PIPE_USAGE_DEFAULT;
  253.          break;
  254.       case GL_DYNAMIC_DRAW:
  255.       case GL_DYNAMIC_COPY:
  256.          pipe_usage = PIPE_USAGE_DYNAMIC;
  257.          break;
  258.       case GL_STREAM_DRAW:
  259.       case GL_STREAM_COPY:
  260.          /* XXX: Remove this test and fall-through when we have PBO unpacking
  261.           * acceleration. Right now, PBO unpacking is done by the CPU, so we
  262.           * have to make sure CPU reads are fast.
  263.           */
  264.          if (target != GL_PIXEL_UNPACK_BUFFER_ARB) {
  265.             pipe_usage = PIPE_USAGE_STREAM;
  266.             break;
  267.          }
  268.          /* fall through */
  269.       case GL_STATIC_READ:
  270.       case GL_DYNAMIC_READ:
  271.       case GL_STREAM_READ:
  272.          pipe_usage = PIPE_USAGE_STAGING;
  273.          break;
  274.       }
  275.    }
  276.  
  277.    /* Set flags. */
  278.    if (storageFlags & GL_MAP_PERSISTENT_BIT)
  279.       pipe_flags |= PIPE_RESOURCE_FLAG_MAP_PERSISTENT;
  280.    if (storageFlags & GL_MAP_COHERENT_BIT)
  281.       pipe_flags |= PIPE_RESOURCE_FLAG_MAP_COHERENT;
  282.  
  283.    pipe_resource_reference( &st_obj->buffer, NULL );
  284.  
  285.    if (ST_DEBUG & DEBUG_BUFFER) {
  286.       debug_printf("Create buffer size %" PRId64 " bind 0x%x\n",
  287.                    (int64_t) size, bind);
  288.    }
  289.  
  290.    if (size != 0) {
  291.       struct pipe_screen *screen = pipe->screen;
  292.       struct pipe_resource buffer;
  293.  
  294.       memset(&buffer, 0, sizeof buffer);
  295.       buffer.target = PIPE_BUFFER;
  296.       buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */
  297.       buffer.bind = bind;
  298.       buffer.usage = pipe_usage;
  299.       buffer.flags = pipe_flags;
  300.       buffer.width0 = size;
  301.       buffer.height0 = 1;
  302.       buffer.depth0 = 1;
  303.       buffer.array_size = 1;
  304.  
  305.       if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {
  306.          st_obj->buffer =
  307.             screen->resource_from_user_memory(screen, &buffer, (void*)data);
  308.       }
  309.       else {
  310.          st_obj->buffer = screen->resource_create(screen, &buffer);
  311.  
  312.          if (st_obj->buffer && data)
  313.             pipe_buffer_write(pipe, st_obj->buffer, 0, size, data);
  314.       }
  315.  
  316.       if (!st_obj->buffer) {
  317.          /* out of memory */
  318.          st_obj->Base.Size = 0;
  319.          return GL_FALSE;
  320.       }
  321.    }
  322.  
  323.    /* BufferData may change an array or uniform buffer, need to update it */
  324.    st->dirty.st |= ST_NEW_VERTEX_ARRAYS | ST_NEW_UNIFORM_BUFFER;
  325.  
  326.    return GL_TRUE;
  327. }
  328.  
  329.  
  330. /**
  331.  * Called via glMapBufferRange().
  332.  */
  333. static void *
  334. st_bufferobj_map_range(struct gl_context *ctx,
  335.                        GLintptr offset, GLsizeiptr length, GLbitfield access,
  336.                        struct gl_buffer_object *obj,
  337.                        gl_map_buffer_index index)
  338. {
  339.    struct pipe_context *pipe = st_context(ctx)->pipe;
  340.    struct st_buffer_object *st_obj = st_buffer_object(obj);
  341.    enum pipe_transfer_usage flags = 0x0;
  342.  
  343.    if (access & GL_MAP_WRITE_BIT)
  344.       flags |= PIPE_TRANSFER_WRITE;
  345.  
  346.    if (access & GL_MAP_READ_BIT)
  347.       flags |= PIPE_TRANSFER_READ;
  348.  
  349.    if (access & GL_MAP_FLUSH_EXPLICIT_BIT)
  350.       flags |= PIPE_TRANSFER_FLUSH_EXPLICIT;
  351.  
  352.    if (access & GL_MAP_INVALIDATE_BUFFER_BIT) {
  353.       flags |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
  354.    }
  355.    else if (access & GL_MAP_INVALIDATE_RANGE_BIT) {
  356.       if (offset == 0 && length == obj->Size)
  357.          flags |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
  358.       else
  359.          flags |= PIPE_TRANSFER_DISCARD_RANGE;
  360.    }
  361.  
  362.    if (access & GL_MAP_UNSYNCHRONIZED_BIT)
  363.       flags |= PIPE_TRANSFER_UNSYNCHRONIZED;
  364.  
  365.    if (access & GL_MAP_PERSISTENT_BIT)
  366.       flags |= PIPE_TRANSFER_PERSISTENT;
  367.  
  368.    if (access & GL_MAP_COHERENT_BIT)
  369.       flags |= PIPE_TRANSFER_COHERENT;
  370.  
  371.    /* ... other flags ...
  372.     */
  373.  
  374.    if (access & MESA_MAP_NOWAIT_BIT)
  375.       flags |= PIPE_TRANSFER_DONTBLOCK;
  376.  
  377.    assert(offset >= 0);
  378.    assert(length >= 0);
  379.    assert(offset < obj->Size);
  380.    assert(offset + length <= obj->Size);
  381.  
  382.    obj->Mappings[index].Pointer = pipe_buffer_map_range(pipe,
  383.                                         st_obj->buffer,
  384.                                         offset, length,
  385.                                         flags,
  386.                                         &st_obj->transfer[index]);
  387.    if (obj->Mappings[index].Pointer) {
  388.       obj->Mappings[index].Offset = offset;
  389.       obj->Mappings[index].Length = length;
  390.       obj->Mappings[index].AccessFlags = access;
  391.    }
  392.    else {
  393.       st_obj->transfer[index] = NULL;
  394.    }
  395.  
  396.    return obj->Mappings[index].Pointer;
  397. }
  398.  
  399.  
  400. static void
  401. st_bufferobj_flush_mapped_range(struct gl_context *ctx,
  402.                                 GLintptr offset, GLsizeiptr length,
  403.                                 struct gl_buffer_object *obj,
  404.                                 gl_map_buffer_index index)
  405. {
  406.    struct pipe_context *pipe = st_context(ctx)->pipe;
  407.    struct st_buffer_object *st_obj = st_buffer_object(obj);
  408.  
  409.    /* Subrange is relative to mapped range */
  410.    assert(offset >= 0);
  411.    assert(length >= 0);
  412.    assert(offset + length <= obj->Mappings[index].Length);
  413.    assert(obj->Mappings[index].Pointer);
  414.  
  415.    if (!length)
  416.       return;
  417.  
  418.    pipe_buffer_flush_mapped_range(pipe, st_obj->transfer[index],
  419.                                   obj->Mappings[index].Offset + offset,
  420.                                   length);
  421. }
  422.  
  423.  
  424. /**
  425.  * Called via glUnmapBufferARB().
  426.  */
  427. static GLboolean
  428. st_bufferobj_unmap(struct gl_context *ctx, struct gl_buffer_object *obj,
  429.                    gl_map_buffer_index index)
  430. {
  431.    struct pipe_context *pipe = st_context(ctx)->pipe;
  432.    struct st_buffer_object *st_obj = st_buffer_object(obj);
  433.  
  434.    if (obj->Mappings[index].Length)
  435.       pipe_buffer_unmap(pipe, st_obj->transfer[index]);
  436.  
  437.    st_obj->transfer[index] = NULL;
  438.    obj->Mappings[index].Pointer = NULL;
  439.    obj->Mappings[index].Offset = 0;
  440.    obj->Mappings[index].Length = 0;
  441.    return GL_TRUE;
  442. }
  443.  
  444.  
  445. /**
  446.  * Called via glCopyBufferSubData().
  447.  */
  448. static void
  449. st_copy_buffer_subdata(struct gl_context *ctx,
  450.                        struct gl_buffer_object *src,
  451.                        struct gl_buffer_object *dst,
  452.                        GLintptr readOffset, GLintptr writeOffset,
  453.                        GLsizeiptr size)
  454. {
  455.    struct pipe_context *pipe = st_context(ctx)->pipe;
  456.    struct st_buffer_object *srcObj = st_buffer_object(src);
  457.    struct st_buffer_object *dstObj = st_buffer_object(dst);
  458.    struct pipe_box box;
  459.  
  460.    if (!size)
  461.       return;
  462.  
  463.    /* buffer should not already be mapped */
  464.    assert(!_mesa_check_disallowed_mapping(src));
  465.    assert(!_mesa_check_disallowed_mapping(dst));
  466.  
  467.    u_box_1d(readOffset, size, &box);
  468.  
  469.    pipe->resource_copy_region(pipe, dstObj->buffer, 0, writeOffset, 0, 0,
  470.                               srcObj->buffer, 0, &box);
  471. }
  472.  
  473. /**
  474.  * Called via glClearBufferSubData().
  475.  */
  476. static void
  477. st_clear_buffer_subdata(struct gl_context *ctx,
  478.                         GLintptr offset, GLsizeiptr size,
  479.                         const GLvoid *clearValue,
  480.                         GLsizeiptr clearValueSize,
  481.                         struct gl_buffer_object *bufObj)
  482. {
  483.    struct pipe_context *pipe = st_context(ctx)->pipe;
  484.    struct st_buffer_object *buf = st_buffer_object(bufObj);
  485.    static const char zeros[16] = {0};
  486.  
  487.    if (!pipe->clear_buffer) {
  488.       _mesa_ClearBufferSubData_sw(ctx, offset, size,
  489.                                   clearValue, clearValueSize, bufObj);
  490.       return;
  491.    }
  492.  
  493.    if (!clearValue)
  494.       clearValue = zeros;
  495.  
  496.    pipe->clear_buffer(pipe, buf->buffer, offset, size,
  497.                       clearValue, clearValueSize);
  498. }
  499.  
  500.  
  501. /* TODO: if buffer wasn't created with appropriate usage flags, need
  502.  * to recreate it now and copy contents -- or possibly create a
  503.  * gallium entrypoint to extend the usage flags and let the driver
  504.  * decide if a copy is necessary.
  505.  */
  506. void
  507. st_bufferobj_validate_usage(struct st_context *st,
  508.                             struct st_buffer_object *obj,
  509.                             unsigned usage)
  510. {
  511. }
  512.  
  513.  
  514. void
  515. st_init_bufferobject_functions(struct dd_function_table *functions)
  516. {
  517.    /* plug in default driver fallbacks (such as for ClearBufferSubData) */
  518.    _mesa_init_buffer_object_functions(functions);
  519.  
  520.    functions->NewBufferObject = st_bufferobj_alloc;
  521.    functions->DeleteBuffer = st_bufferobj_free;
  522.    functions->BufferData = st_bufferobj_data;
  523.    functions->BufferSubData = st_bufferobj_subdata;
  524.    functions->GetBufferSubData = st_bufferobj_get_subdata;
  525.    functions->MapBufferRange = st_bufferobj_map_range;
  526.    functions->FlushMappedBufferRange = st_bufferobj_flush_mapped_range;
  527.    functions->UnmapBuffer = st_bufferobj_unmap;
  528.    functions->CopyBufferSubData = st_copy_buffer_subdata;
  529.    functions->ClearBufferSubData = st_clear_buffer_subdata;
  530.  
  531.    /* For GL_APPLE_vertex_array_object */
  532.    functions->NewArrayObject = _mesa_new_vao;
  533.    functions->DeleteArrayObject = _mesa_delete_vao;
  534. }
  535.