Home | History | Annotate | Download | only in radeon
      1 /*
      2  * Copyright 2009 Maciej Cencora <m.cencora (at) gmail.com>
      3  *
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining
      7  * a 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, sublicense, 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
     16  * portions of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     21  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
     22  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     23  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     24  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  */
     27 
     28 #include "main/imports.h"
     29 #include "main/mtypes.h"
     30 #include "main/bufferobj.h"
     31 
     32 #include "radeon_common.h"
     33 #include "radeon_buffer_objects.h"
     34 
     35 struct radeon_buffer_object *
     36 get_radeon_buffer_object(struct gl_buffer_object *obj)
     37 {
     38     return (struct radeon_buffer_object *) obj;
     39 }
     40 
     41 static struct gl_buffer_object *
     42 radeonNewBufferObject(struct gl_context * ctx,
     43                       GLuint name)
     44 {
     45     struct radeon_buffer_object *obj = CALLOC_STRUCT(radeon_buffer_object);
     46 
     47     _mesa_initialize_buffer_object(ctx, &obj->Base, name);
     48 
     49     obj->bo = NULL;
     50 
     51     return &obj->Base;
     52 }
     53 
     54 /**
     55  * Called via glDeleteBuffersARB().
     56  */
     57 static void
     58 radeonDeleteBufferObject(struct gl_context * ctx,
     59                          struct gl_buffer_object *obj)
     60 {
     61     struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
     62     int i;
     63 
     64     for (i = 0; i < MAP_COUNT; i++) {
     65        if (obj->Mappings[i].Pointer) {
     66            radeon_bo_unmap(radeon_obj->bo);
     67        }
     68     }
     69 
     70     if (radeon_obj->bo) {
     71         radeon_bo_unref(radeon_obj->bo);
     72     }
     73 
     74     _mesa_delete_buffer_object(ctx, obj);
     75 }
     76 
     77 
     78 /**
     79  * Allocate space for and store data in a buffer object.  Any data that was
     80  * previously stored in the buffer object is lost.  If data is NULL,
     81  * memory will be allocated, but no copy will occur.
     82  * Called via ctx->Driver.BufferData().
     83  * \return GL_TRUE for success, GL_FALSE if out of memory
     84  */
     85 static GLboolean
     86 radeonBufferData(struct gl_context * ctx,
     87                  GLenum target,
     88                  GLsizeiptrARB size,
     89                  const GLvoid * data,
     90                  GLenum usage,
     91                  GLbitfield storageFlags,
     92                  struct gl_buffer_object *obj)
     93 {
     94     radeonContextPtr radeon = RADEON_CONTEXT(ctx);
     95     struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
     96 
     97     radeon_obj->Base.Size = size;
     98     radeon_obj->Base.Usage = usage;
     99     radeon_obj->Base.StorageFlags = storageFlags;
    100 
    101     if (radeon_obj->bo != NULL) {
    102         radeon_bo_unref(radeon_obj->bo);
    103         radeon_obj->bo = NULL;
    104     }
    105 
    106     if (size != 0) {
    107         radeon_obj->bo = radeon_bo_open(radeon->radeonScreen->bom,
    108                                         0,
    109                                         size,
    110                                         ctx->Const.MinMapBufferAlignment,
    111                                         RADEON_GEM_DOMAIN_GTT,
    112                                         0);
    113 
    114         if (!radeon_obj->bo)
    115             return GL_FALSE;
    116 
    117         if (data != NULL) {
    118             radeon_bo_map(radeon_obj->bo, GL_TRUE);
    119 
    120             memcpy(radeon_obj->bo->ptr, data, size);
    121 
    122             radeon_bo_unmap(radeon_obj->bo);
    123         }
    124     }
    125     return GL_TRUE;
    126 }
    127 
    128 /**
    129  * Replace data in a subrange of buffer object.  If the data range
    130  * specified by size + offset extends beyond the end of the buffer or
    131  * if data is NULL, no copy is performed.
    132  * Called via glBufferSubDataARB().
    133  */
    134 static void
    135 radeonBufferSubData(struct gl_context * ctx,
    136                     GLintptrARB offset,
    137                     GLsizeiptrARB size,
    138                     const GLvoid * data,
    139                     struct gl_buffer_object *obj)
    140 {
    141     radeonContextPtr radeon = RADEON_CONTEXT(ctx);
    142     struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
    143 
    144     if (radeon_bo_is_referenced_by_cs(radeon_obj->bo, radeon->cmdbuf.cs)) {
    145         radeon_firevertices(radeon);
    146     }
    147 
    148     radeon_bo_map(radeon_obj->bo, GL_TRUE);
    149 
    150     memcpy(radeon_obj->bo->ptr + offset, data, size);
    151 
    152     radeon_bo_unmap(radeon_obj->bo);
    153 }
    154 
    155 /**
    156  * Called via glGetBufferSubDataARB()
    157  */
    158 static void
    159 radeonGetBufferSubData(struct gl_context * ctx,
    160                        GLintptrARB offset,
    161                        GLsizeiptrARB size,
    162                        GLvoid * data,
    163                        struct gl_buffer_object *obj)
    164 {
    165     struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
    166 
    167     radeon_bo_map(radeon_obj->bo, GL_FALSE);
    168 
    169     memcpy(data, radeon_obj->bo->ptr + offset, size);
    170 
    171     radeon_bo_unmap(radeon_obj->bo);
    172 }
    173 
    174 /**
    175  * Called via glMapBuffer() and glMapBufferRange()
    176  */
    177 static void *
    178 radeonMapBufferRange(struct gl_context * ctx,
    179 		     GLintptr offset, GLsizeiptr length,
    180 		     GLbitfield access, struct gl_buffer_object *obj,
    181                      gl_map_buffer_index index)
    182 {
    183     struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
    184     const GLboolean write_only =
    185        (access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == GL_MAP_WRITE_BIT;
    186 
    187     if (write_only) {
    188         ctx->Driver.Flush(ctx);
    189     }
    190 
    191     if (radeon_obj->bo == NULL) {
    192         obj->Mappings[index].Pointer = NULL;
    193         return NULL;
    194     }
    195 
    196     obj->Mappings[index].Offset = offset;
    197     obj->Mappings[index].Length = length;
    198     obj->Mappings[index].AccessFlags = access;
    199 
    200     radeon_bo_map(radeon_obj->bo, write_only);
    201 
    202     obj->Mappings[index].Pointer = radeon_obj->bo->ptr + offset;
    203     return obj->Mappings[index].Pointer;
    204 }
    205 
    206 
    207 /**
    208  * Called via glUnmapBufferARB()
    209  */
    210 static GLboolean
    211 radeonUnmapBuffer(struct gl_context * ctx,
    212                   struct gl_buffer_object *obj,
    213                   gl_map_buffer_index index)
    214 {
    215     struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
    216 
    217     if (radeon_obj->bo != NULL) {
    218         radeon_bo_unmap(radeon_obj->bo);
    219     }
    220 
    221     obj->Mappings[index].Pointer = NULL;
    222     obj->Mappings[index].Offset = 0;
    223     obj->Mappings[index].Length = 0;
    224 
    225     return GL_TRUE;
    226 }
    227 
    228 void
    229 radeonInitBufferObjectFuncs(struct dd_function_table *functions)
    230 {
    231     functions->NewBufferObject = radeonNewBufferObject;
    232     functions->DeleteBuffer = radeonDeleteBufferObject;
    233     functions->BufferData = radeonBufferData;
    234     functions->BufferSubData = radeonBufferSubData;
    235     functions->GetBufferSubData = radeonGetBufferSubData;
    236     functions->MapBufferRange = radeonMapBufferRange;
    237     functions->UnmapBuffer = radeonUnmapBuffer;
    238 }
    239