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