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