Subversion Repositories Kolibri OS

Rev

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