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