1/* 2 * Copyright 2009 Maciej Cencora <m.cencora@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 "radeon_buffer_objects.h" 29 30#include "main/imports.h" 31#include "main/mtypes.h" 32#include "main/bufferobj.h" 33 34#include "radeon_common.h" 35 36struct radeon_buffer_object * 37get_radeon_buffer_object(struct gl_buffer_object *obj) 38{ 39 return (struct radeon_buffer_object *) obj; 40} 41 42static struct gl_buffer_object * 43radeonNewBufferObject(struct gl_context * ctx, 44 GLuint name, 45 GLenum target) 46{ 47 struct radeon_buffer_object *obj = CALLOC_STRUCT(radeon_buffer_object); 48 49 _mesa_initialize_buffer_object(ctx, &obj->Base, name, target); 50 51 obj->bo = NULL; 52 53 return &obj->Base; 54} 55 56/** 57 * Called via glDeleteBuffersARB(). 58 */ 59static void 60radeonDeleteBufferObject(struct gl_context * ctx, 61 struct gl_buffer_object *obj) 62{ 63 struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); 64 65 if (obj->Pointer) { 66 radeon_bo_unmap(radeon_obj->bo); 67 } 68 69 if (radeon_obj->bo) { 70 radeon_bo_unref(radeon_obj->bo); 71 } 72 73 free(radeon_obj); 74} 75 76 77/** 78 * Allocate space for and store data in a buffer object. Any data that was 79 * previously stored in the buffer object is lost. If data is NULL, 80 * memory will be allocated, but no copy will occur. 81 * Called via ctx->Driver.BufferData(). 82 * \return GL_TRUE for success, GL_FALSE if out of memory 83 */ 84static GLboolean 85radeonBufferData(struct gl_context * ctx, 86 GLenum target, 87 GLsizeiptrARB size, 88 const GLvoid * data, 89 GLenum usage, 90 struct gl_buffer_object *obj) 91{ 92 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 93 struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); 94 95 radeon_obj->Base.Size = size; 96 radeon_obj->Base.Usage = usage; 97 98 if (radeon_obj->bo != NULL) { 99 radeon_bo_unref(radeon_obj->bo); 100 radeon_obj->bo = NULL; 101 } 102 103 if (size != 0) { 104 radeon_obj->bo = radeon_bo_open(radeon->radeonScreen->bom, 105 0, 106 size, 107 32, 108 RADEON_GEM_DOMAIN_GTT, 109 0); 110 111 if (!radeon_obj->bo) 112 return GL_FALSE; 113 114 if (data != NULL) { 115 radeon_bo_map(radeon_obj->bo, GL_TRUE); 116 117 memcpy(radeon_obj->bo->ptr, data, size); 118 119 radeon_bo_unmap(radeon_obj->bo); 120 } 121 } 122 return GL_TRUE; 123} 124 125/** 126 * Replace data in a subrange of buffer object. If the data range 127 * specified by size + offset extends beyond the end of the buffer or 128 * if data is NULL, no copy is performed. 129 * Called via glBufferSubDataARB(). 130 */ 131static void 132radeonBufferSubData(struct gl_context * ctx, 133 GLintptrARB offset, 134 GLsizeiptrARB size, 135 const GLvoid * data, 136 struct gl_buffer_object *obj) 137{ 138 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 139 struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); 140 141 if (radeon_bo_is_referenced_by_cs(radeon_obj->bo, radeon->cmdbuf.cs)) { 142 radeon_firevertices(radeon); 143 } 144 145 radeon_bo_map(radeon_obj->bo, GL_TRUE); 146 147 memcpy(radeon_obj->bo->ptr + offset, data, size); 148 149 radeon_bo_unmap(radeon_obj->bo); 150} 151 152/** 153 * Called via glGetBufferSubDataARB() 154 */ 155static void 156radeonGetBufferSubData(struct gl_context * ctx, 157 GLintptrARB offset, 158 GLsizeiptrARB size, 159 GLvoid * data, 160 struct gl_buffer_object *obj) 161{ 162 struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); 163 164 radeon_bo_map(radeon_obj->bo, GL_FALSE); 165 166 memcpy(data, radeon_obj->bo->ptr + offset, size); 167 168 radeon_bo_unmap(radeon_obj->bo); 169} 170 171/** 172 * Called via glMapBuffer() and glMapBufferRange() 173 */ 174static void * 175radeonMapBufferRange(struct gl_context * ctx, 176 GLintptr offset, GLsizeiptr length, 177 GLbitfield access, struct gl_buffer_object *obj) 178{ 179 struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); 180 const GLboolean write_only = 181 (access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == GL_MAP_WRITE_BIT; 182 183 if (write_only) { 184 ctx->Driver.Flush(ctx); 185 } 186 187 if (radeon_obj->bo == NULL) { 188 obj->Pointer = NULL; 189 return NULL; 190 } 191 192 obj->Offset = offset; 193 obj->Length = length; 194 obj->AccessFlags = access; 195 196 radeon_bo_map(radeon_obj->bo, write_only); 197 198 obj->Pointer = radeon_obj->bo->ptr + offset; 199 return obj->Pointer; 200} 201 202 203/** 204 * Called via glUnmapBufferARB() 205 */ 206static GLboolean 207radeonUnmapBuffer(struct gl_context * ctx, 208 struct gl_buffer_object *obj) 209{ 210 struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); 211 212 if (radeon_obj->bo != NULL) { 213 radeon_bo_unmap(radeon_obj->bo); 214 } 215 216 obj->Pointer = NULL; 217 obj->Offset = 0; 218 obj->Length = 0; 219 220 return GL_TRUE; 221} 222 223void 224radeonInitBufferObjectFuncs(struct dd_function_table *functions) 225{ 226 functions->NewBufferObject = radeonNewBufferObject; 227 functions->DeleteBuffer = radeonDeleteBufferObject; 228 functions->BufferData = radeonBufferData; 229 functions->BufferSubData = radeonBufferSubData; 230 functions->GetBufferSubData = radeonGetBufferSubData; 231 functions->MapBufferRange = radeonMapBufferRange; 232 functions->UnmapBuffer = radeonUnmapBuffer; 233} 234