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