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 "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 36 struct radeon_buffer_object * 37 get_radeon_buffer_object(struct gl_buffer_object *obj) 38 { 39 return (struct radeon_buffer_object *) obj; 40 } 41 42 static struct gl_buffer_object * 43 radeonNewBufferObject(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 */ 59 static void 60 radeonDeleteBufferObject(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 */ 84 static GLboolean 85 radeonBufferData(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 */ 131 static void 132 radeonBufferSubData(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 */ 155 static void 156 radeonGetBufferSubData(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 */ 174 static void * 175 radeonMapBufferRange(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 */ 206 static GLboolean 207 radeonUnmapBuffer(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 223 void 224 radeonInitBufferObjectFuncs(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