st_cb_bufferobjects.c revision 34bb024cf2d02d5d5cb672ead05fa131bdff6dd8
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#include "main/imports.h" 30#include "main/mtypes.h" 31#include "main/bufferobj.h" 32 33#include "st_inlines.h" 34#include "st_context.h" 35#include "st_cb_bufferobjects.h" 36 37#include "pipe/p_context.h" 38#include "pipe/p_defines.h" 39#include "pipe/p_inlines.h" 40 41 42 43/* Pixel buffers and Vertex/index buffers are handled through these 44 * mesa callbacks. Framebuffer/Renderbuffer objects are 45 * created/managed elsewhere. 46 */ 47 48 49 50/** 51 * There is some duplication between mesa's bufferobjects and our 52 * bufmgr buffers. Both have an integer handle and a hashtable to 53 * lookup an opaque structure. It would be nice if the handles and 54 * internal structure where somehow shared. 55 */ 56static struct gl_buffer_object * 57st_bufferobj_alloc(GLcontext *ctx, GLuint name, GLenum target) 58{ 59 struct st_buffer_object *st_obj = ST_CALLOC_STRUCT(st_buffer_object); 60 61 if (!st_obj) 62 return NULL; 63 64 _mesa_initialize_buffer_object(&st_obj->Base, name, target); 65 66 return &st_obj->Base; 67} 68 69 70 71/** 72 * Deallocate/free a vertex/pixel buffer object. 73 * Called via glDeleteBuffersARB(). 74 */ 75static void 76st_bufferobj_free(GLcontext *ctx, struct gl_buffer_object *obj) 77{ 78 struct st_buffer_object *st_obj = st_buffer_object(obj); 79 80 if (st_obj->buffer) 81 pipe_buffer_reference(&st_obj->buffer, NULL); 82 83 _mesa_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 */ 94static void 95st_bufferobj_subdata(GLcontext *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 if (offset >= st_obj->size || size > (st_obj->size - offset)) 104 return; 105 106 st_cond_flush_pipe_buffer_write(st_context(ctx), st_obj->buffer, 107 offset, size, data); 108} 109 110 111/** 112 * Called via glGetBufferSubDataARB(). 113 */ 114static void 115st_bufferobj_get_subdata(GLcontext *ctx, 116 GLenum target, 117 GLintptrARB offset, 118 GLsizeiptrARB size, 119 GLvoid * data, struct gl_buffer_object *obj) 120{ 121 struct st_buffer_object *st_obj = st_buffer_object(obj); 122 123 if (offset >= st_obj->size || size > (st_obj->size - offset)) 124 return; 125 126 st_cond_flush_pipe_buffer_read(st_context(ctx), st_obj->buffer, 127 offset, size, data); 128} 129 130 131/** 132 * Allocate space for and store data in a buffer object. Any data that was 133 * previously stored in the buffer object is lost. If data is NULL, 134 * memory will be allocated, but no copy will occur. 135 * Called via glBufferDataARB(). 136 */ 137static void 138st_bufferobj_data(GLcontext *ctx, 139 GLenum target, 140 GLsizeiptrARB size, 141 const GLvoid * data, 142 GLenum usage, 143 struct gl_buffer_object *obj) 144{ 145 struct st_context *st = st_context(ctx); 146 struct pipe_context *pipe = st->pipe; 147 struct st_buffer_object *st_obj = st_buffer_object(obj); 148 unsigned buffer_usage; 149 150 st_obj->Base.Size = size; 151 st_obj->Base.Usage = usage; 152 153 switch(target) { 154 case GL_PIXEL_PACK_BUFFER_ARB: 155 case GL_PIXEL_UNPACK_BUFFER_ARB: 156 buffer_usage = PIPE_BUFFER_USAGE_PIXEL; 157 break; 158 case GL_ARRAY_BUFFER_ARB: 159 buffer_usage = PIPE_BUFFER_USAGE_VERTEX; 160 break; 161 case GL_ELEMENT_ARRAY_BUFFER_ARB: 162 buffer_usage = PIPE_BUFFER_USAGE_INDEX; 163 break; 164 default: 165 buffer_usage = 0; 166 } 167 168 pipe_buffer_reference( &st_obj->buffer, NULL ); 169 170 st_obj->buffer = pipe_buffer_create( pipe->screen, 32, buffer_usage, size ); 171 172 if (!st_obj->buffer) { 173 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB"); 174 return; 175 } 176 177 st_obj->size = size; 178 179 if (data) 180 st_no_flush_pipe_buffer_write(st_context(ctx), st_obj->buffer, 0, 181 size, data); 182} 183 184 185/** 186 * Called via glMapBufferARB(). 187 */ 188static void * 189st_bufferobj_map(GLcontext *ctx, GLenum target, GLenum access, 190 struct gl_buffer_object *obj) 191{ 192 struct st_buffer_object *st_obj = st_buffer_object(obj); 193 GLuint flags; 194 195 switch (access) { 196 case GL_WRITE_ONLY: 197 flags = PIPE_BUFFER_USAGE_CPU_WRITE; 198 break; 199 case GL_READ_ONLY: 200 flags = PIPE_BUFFER_USAGE_CPU_READ; 201 break; 202 case GL_READ_WRITE: 203 /* fall-through */ 204 default: 205 flags = PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE; 206 break; 207 } 208 209 obj->Pointer = st_cond_flush_pipe_buffer_map(st_context(ctx), 210 st_obj->buffer, 211 flags); 212 if(obj->Pointer) { 213 obj->Offset = 0; 214 obj->Length = obj->Size; 215 } 216 return obj->Pointer; 217} 218 219 220 221/** 222 * Called via glMapBufferRange(). 223 */ 224static void * 225st_bufferobj_map_range(GLcontext *ctx, GLenum target, 226 GLintptr offset, GLsizeiptr length, GLbitfield access, 227 struct gl_buffer_object *obj) 228{ 229 struct pipe_context *pipe = st_context(ctx)->pipe; 230 struct st_buffer_object *st_obj = st_buffer_object(obj); 231 GLuint flags = 0; 232 char *map; 233 234 if (access & GL_MAP_WRITE_BIT) 235 flags |= PIPE_BUFFER_USAGE_CPU_WRITE; 236 237 if (access & GL_MAP_READ_BIT) 238 flags |= PIPE_BUFFER_USAGE_CPU_READ; 239 240 /* ... other flags ... 241 */ 242 243 if (access & MESA_MAP_NOWAIT_BIT) 244 flags |= PIPE_BUFFER_USAGE_DONTBLOCK; 245 246 assert(offset >= 0); 247 assert(length >= 0); 248 assert(offset < obj->Size); 249 assert(offset + length <= obj->Size); 250 251 map = obj->Pointer = pipe_buffer_map_range(pipe->screen, st_obj->buffer, offset, length, flags); 252 if(obj->Pointer) { 253 obj->Offset = 0; 254 obj->Length = length; 255 map += offset; 256 } 257 258 return map; 259} 260 261 262static void 263st_bufferobj_flush_mapped_range(GLcontext *ctx, GLenum target, 264 GLintptr offset, GLsizeiptr length, 265 struct gl_buffer_object *obj) 266{ 267 struct pipe_context *pipe = st_context(ctx)->pipe; 268 struct st_buffer_object *st_obj = st_buffer_object(obj); 269 270 /* Subrange is relative to mapped range */ 271 assert(offset >= 0); 272 assert(length >= 0); 273 assert(offset + length <= obj->Length); 274 275 pipe_buffer_flush_mapped_range(pipe->screen, st_obj->buffer, 276 obj->Offset + offset, length); 277} 278 279 280/** 281 * Called via glUnmapBufferARB(). 282 */ 283static GLboolean 284st_bufferobj_unmap(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj) 285{ 286 struct pipe_context *pipe = st_context(ctx)->pipe; 287 struct st_buffer_object *st_obj = st_buffer_object(obj); 288 289 pipe_buffer_unmap(pipe->screen, st_obj->buffer); 290 obj->Pointer = NULL; 291 obj->Offset = 0; 292 obj->Length = 0; 293 return GL_TRUE; 294} 295 296 297void 298st_init_bufferobject_functions(struct dd_function_table *functions) 299{ 300 functions->NewBufferObject = st_bufferobj_alloc; 301 functions->DeleteBuffer = st_bufferobj_free; 302 functions->BufferData = st_bufferobj_data; 303 functions->BufferSubData = st_bufferobj_subdata; 304 functions->GetBufferSubData = st_bufferobj_get_subdata; 305 functions->MapBuffer = st_bufferobj_map; 306 functions->MapBufferRange = st_bufferobj_map_range; 307 functions->FlushMappedBufferRange = st_bufferobj_flush_mapped_range; 308 functions->UnmapBuffer = st_bufferobj_unmap; 309} 310