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