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