Merge commit 'origin/gallium-0.1' into gallium-0.2
[mesa.git] / src / mesa / drivers / dri / intel / intel_buffer_objects.c
1 /**************************************************************************
2 *
3 * Copyright 2003 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 "intel_context.h"
34 #include "intel_buffer_objects.h"
35 #include "intel_batchbuffer.h"
36 #include "intel_regions.h"
37
38 static GLboolean intel_bufferobj_unmap(GLcontext * ctx,
39 GLenum target,
40 struct gl_buffer_object *obj);
41
42 /** Allocates a new dri_bo to store the data for the buffer object. */
43 static void
44 intel_bufferobj_alloc_buffer(struct intel_context *intel,
45 struct intel_buffer_object *intel_obj)
46 {
47 intel_obj->buffer = dri_bo_alloc(intel->bufmgr, "bufferobj",
48 intel_obj->Base.Size, 64);
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 intel_bufferobj_alloc(GLcontext * ctx, GLuint name, GLenum target)
59 {
60 struct intel_buffer_object *obj = CALLOC_STRUCT(intel_buffer_object);
61
62 _mesa_initialize_buffer_object(&obj->Base, name, target);
63
64 obj->buffer = NULL;
65
66 return &obj->Base;
67 }
68
69 /* Break the COW tie to the region. The region gets to keep the data.
70 */
71 void
72 intel_bufferobj_release_region(struct intel_context *intel,
73 struct intel_buffer_object *intel_obj)
74 {
75 assert(intel_obj->region->buffer == intel_obj->buffer);
76 intel_obj->region->pbo = NULL;
77 intel_obj->region = NULL;
78
79 dri_bo_unreference(intel_obj->buffer);
80 intel_obj->buffer = NULL;
81 }
82
83 /* Break the COW tie to the region. Both the pbo and the region end
84 * up with a copy of the data.
85 */
86 void
87 intel_bufferobj_cow(struct intel_context *intel,
88 struct intel_buffer_object *intel_obj)
89 {
90 assert(intel_obj->region);
91 intel_region_cow(intel, intel_obj->region);
92 }
93
94
95 /**
96 * Deallocate/free a vertex/pixel buffer object.
97 * Called via glDeleteBuffersARB().
98 */
99 static void
100 intel_bufferobj_free(GLcontext * ctx, struct gl_buffer_object *obj)
101 {
102 struct intel_context *intel = intel_context(ctx);
103 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
104
105 assert(intel_obj);
106
107 /* Buffer objects are automatically unmapped when deleting according
108 * to the spec.
109 */
110 if (obj->Pointer)
111 intel_bufferobj_unmap(ctx, 0, obj);
112
113 if (intel_obj->region) {
114 intel_bufferobj_release_region(intel, intel_obj);
115 }
116 else if (intel_obj->buffer) {
117 dri_bo_unreference(intel_obj->buffer);
118 }
119
120 _mesa_free(intel_obj);
121 }
122
123
124
125 /**
126 * Allocate space for and store data in a buffer object. Any data that was
127 * previously stored in the buffer object is lost. If data is NULL,
128 * memory will be allocated, but no copy will occur.
129 * Called via glBufferDataARB().
130 */
131 static void
132 intel_bufferobj_data(GLcontext * ctx,
133 GLenum target,
134 GLsizeiptrARB size,
135 const GLvoid * data,
136 GLenum usage, struct gl_buffer_object *obj)
137 {
138 struct intel_context *intel = intel_context(ctx);
139 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
140
141 intel_obj->Base.Size = size;
142 intel_obj->Base.Usage = usage;
143
144 /* Buffer objects are automatically unmapped when creating new data buffers
145 * according to the spec.
146 */
147 if (obj->Pointer)
148 intel_bufferobj_unmap(ctx, 0, obj);
149
150 if (intel_obj->region)
151 intel_bufferobj_release_region(intel, intel_obj);
152
153 if (intel_obj->buffer != NULL) {
154 dri_bo_unreference(intel_obj->buffer);
155 intel_obj->buffer = NULL;
156 }
157 if (size != 0) {
158 intel_bufferobj_alloc_buffer(intel, intel_obj);
159
160 if (data != NULL)
161 dri_bo_subdata(intel_obj->buffer, 0, size, data);
162 }
163 }
164
165
166 /**
167 * Replace data in a subrange of buffer object. If the data range
168 * specified by size + offset extends beyond the end of the buffer or
169 * if data is NULL, no copy is performed.
170 * Called via glBufferSubDataARB().
171 */
172 static void
173 intel_bufferobj_subdata(GLcontext * ctx,
174 GLenum target,
175 GLintptrARB offset,
176 GLsizeiptrARB size,
177 const GLvoid * data, struct gl_buffer_object *obj)
178 {
179 struct intel_context *intel = intel_context(ctx);
180 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
181
182 assert(intel_obj);
183
184 if (intel_obj->region)
185 intel_bufferobj_cow(intel, intel_obj);
186
187 dri_bo_subdata(intel_obj->buffer, offset, size, data);
188 }
189
190
191 /**
192 * Called via glGetBufferSubDataARB().
193 */
194 static void
195 intel_bufferobj_get_subdata(GLcontext * ctx,
196 GLenum target,
197 GLintptrARB offset,
198 GLsizeiptrARB size,
199 GLvoid * data, struct gl_buffer_object *obj)
200 {
201 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
202
203 assert(intel_obj);
204 dri_bo_get_subdata(intel_obj->buffer, offset, size, data);
205 }
206
207
208
209 /**
210 * Called via glMapBufferARB().
211 */
212 static void *
213 intel_bufferobj_map(GLcontext * ctx,
214 GLenum target,
215 GLenum access, struct gl_buffer_object *obj)
216 {
217 struct intel_context *intel = intel_context(ctx);
218 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
219
220 /* XXX: Translate access to flags arg below:
221 */
222 assert(intel_obj);
223
224 if (intel_obj->region)
225 intel_bufferobj_cow(intel, intel_obj);
226
227 if (intel_obj->buffer == NULL) {
228 obj->Pointer = NULL;
229 return NULL;
230 }
231
232 dri_bo_map(intel_obj->buffer, GL_TRUE);
233 obj->Pointer = intel_obj->buffer->virtual;
234 return obj->Pointer;
235 }
236
237
238 /**
239 * Called via glMapBufferARB().
240 */
241 static GLboolean
242 intel_bufferobj_unmap(GLcontext * ctx,
243 GLenum target, struct gl_buffer_object *obj)
244 {
245 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
246
247 assert(intel_obj);
248 if (intel_obj->buffer != NULL) {
249 assert(obj->Pointer);
250 dri_bo_unmap(intel_obj->buffer);
251 obj->Pointer = NULL;
252 }
253 return GL_TRUE;
254 }
255
256 dri_bo *
257 intel_bufferobj_buffer(struct intel_context *intel,
258 struct intel_buffer_object *intel_obj, GLuint flag)
259 {
260 if (intel_obj->region) {
261 if (flag == INTEL_WRITE_PART)
262 intel_bufferobj_cow(intel, intel_obj);
263 else if (flag == INTEL_WRITE_FULL) {
264 intel_bufferobj_release_region(intel, intel_obj);
265 intel_bufferobj_alloc_buffer(intel, intel_obj);
266 }
267 }
268
269 return intel_obj->buffer;
270 }
271
272 void
273 intel_bufferobj_init(struct intel_context *intel)
274 {
275 GLcontext *ctx = &intel->ctx;
276
277 ctx->Driver.NewBufferObject = intel_bufferobj_alloc;
278 ctx->Driver.DeleteBuffer = intel_bufferobj_free;
279 ctx->Driver.BufferData = intel_bufferobj_data;
280 ctx->Driver.BufferSubData = intel_bufferobj_subdata;
281 ctx->Driver.GetBufferSubData = intel_bufferobj_get_subdata;
282 ctx->Driver.MapBuffer = intel_bufferobj_map;
283 ctx->Driver.UnmapBuffer = intel_bufferobj_unmap;
284 }