i965: Don't clip everything if FRONT_AND_BACK culling while culling disabled.
[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 _mesa_free(intel_obj->sys_buffer);
106 if (intel_obj->region) {
107 intel_bufferobj_release_region(intel, intel_obj);
108 }
109 else if (intel_obj->buffer) {
110 dri_bo_unreference(intel_obj->buffer);
111 }
112
113 _mesa_free(intel_obj);
114 }
115
116
117
118 /**
119 * Allocate space for and store data in a buffer object. Any data that was
120 * previously stored in the buffer object is lost. If data is NULL,
121 * memory will be allocated, but no copy will occur.
122 * Called via glBufferDataARB().
123 */
124 static void
125 intel_bufferobj_data(GLcontext * ctx,
126 GLenum target,
127 GLsizeiptrARB size,
128 const GLvoid * data,
129 GLenum usage, struct gl_buffer_object *obj)
130 {
131 struct intel_context *intel = intel_context(ctx);
132 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
133
134 intel_obj->Base.Size = size;
135 intel_obj->Base.Usage = usage;
136
137 assert(!obj->Pointer); /* Mesa should have unmapped it */
138
139 if (intel_obj->region)
140 intel_bufferobj_release_region(intel, intel_obj);
141
142 if (intel_obj->buffer != NULL) {
143 dri_bo_unreference(intel_obj->buffer);
144 intel_obj->buffer = NULL;
145 }
146 _mesa_free(intel_obj->sys_buffer);
147 intel_obj->sys_buffer = NULL;
148
149 if (size != 0) {
150 #ifdef I915
151 /* On pre-965, stick VBOs in system memory, as we're always doing swtnl
152 * with their contents anyway.
153 */
154 if (target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER) {
155 intel_obj->sys_buffer = _mesa_malloc(size);
156 if (intel_obj->sys_buffer != NULL) {
157 if (data != NULL)
158 memcpy(intel_obj->sys_buffer, data, size);
159 return;
160 }
161 }
162 #endif
163 intel_bufferobj_alloc_buffer(intel, intel_obj);
164
165 if (data != NULL)
166 dri_bo_subdata(intel_obj->buffer, 0, size, data);
167 }
168 }
169
170
171 /**
172 * Replace data in a subrange of buffer object. If the data range
173 * specified by size + offset extends beyond the end of the buffer or
174 * if data is NULL, no copy is performed.
175 * Called via glBufferSubDataARB().
176 */
177 static void
178 intel_bufferobj_subdata(GLcontext * ctx,
179 GLenum target,
180 GLintptrARB offset,
181 GLsizeiptrARB size,
182 const GLvoid * data, struct gl_buffer_object *obj)
183 {
184 struct intel_context *intel = intel_context(ctx);
185 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
186
187 assert(intel_obj);
188
189 if (intel_obj->region)
190 intel_bufferobj_cow(intel, intel_obj);
191
192 if (intel_obj->sys_buffer)
193 memcpy((char *)intel_obj->sys_buffer + offset, data, size);
194 else
195 dri_bo_subdata(intel_obj->buffer, offset, size, data);
196 }
197
198
199 /**
200 * Called via glGetBufferSubDataARB().
201 */
202 static void
203 intel_bufferobj_get_subdata(GLcontext * ctx,
204 GLenum target,
205 GLintptrARB offset,
206 GLsizeiptrARB size,
207 GLvoid * data, struct gl_buffer_object *obj)
208 {
209 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
210
211 assert(intel_obj);
212 dri_bo_get_subdata(intel_obj->buffer, offset, size, data);
213 }
214
215
216
217 /**
218 * Called via glMapBufferARB().
219 */
220 static void *
221 intel_bufferobj_map(GLcontext * ctx,
222 GLenum target,
223 GLenum access, struct gl_buffer_object *obj)
224 {
225 struct intel_context *intel = intel_context(ctx);
226 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
227 GLboolean read_only = (access == GL_READ_ONLY_ARB);
228 GLboolean write_only = (access == GL_WRITE_ONLY_ARB);
229
230 assert(intel_obj);
231
232 if (intel_obj->sys_buffer) {
233 obj->Pointer = intel_obj->sys_buffer;
234 return obj->Pointer;
235 }
236
237 if (intel_obj->region)
238 intel_bufferobj_cow(intel, intel_obj);
239
240 if (intel_obj->buffer == NULL) {
241 obj->Pointer = NULL;
242 return NULL;
243 }
244
245 if (write_only && intel->intelScreen->kernel_exec_fencing) {
246 drm_intel_gem_bo_map_gtt(intel_obj->buffer);
247 intel_obj->mapped_gtt = GL_TRUE;
248 } else {
249 drm_intel_bo_map(intel_obj->buffer, !read_only);
250 intel_obj->mapped_gtt = GL_FALSE;
251 }
252
253 obj->Pointer = intel_obj->buffer->virtual;
254 return obj->Pointer;
255 }
256
257
258 /**
259 * Called via glMapBufferARB().
260 */
261 static GLboolean
262 intel_bufferobj_unmap(GLcontext * ctx,
263 GLenum target, struct gl_buffer_object *obj)
264 {
265 struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
266
267 assert(intel_obj);
268 if (intel_obj->sys_buffer != NULL) {
269 assert(obj->Pointer);
270 obj->Pointer = NULL;
271 } else if (intel_obj->buffer != NULL) {
272 assert(obj->Pointer);
273 if (intel_obj->mapped_gtt) {
274 drm_intel_gem_bo_unmap_gtt(intel_obj->buffer);
275 } else {
276 drm_intel_bo_unmap(intel_obj->buffer);
277 }
278 obj->Pointer = NULL;
279 }
280 return GL_TRUE;
281 }
282
283 dri_bo *
284 intel_bufferobj_buffer(struct intel_context *intel,
285 struct intel_buffer_object *intel_obj, GLuint flag)
286 {
287 if (intel_obj->region) {
288 if (flag == INTEL_WRITE_PART)
289 intel_bufferobj_cow(intel, intel_obj);
290 else if (flag == INTEL_WRITE_FULL) {
291 intel_bufferobj_release_region(intel, intel_obj);
292 intel_bufferobj_alloc_buffer(intel, intel_obj);
293 }
294 }
295
296 if (intel_obj->buffer == NULL) {
297 intel_bufferobj_alloc_buffer(intel, intel_obj);
298 intel_bufferobj_subdata(&intel->ctx,
299 GL_ARRAY_BUFFER_ARB,
300 0,
301 intel_obj->Base.Size,
302 intel_obj->sys_buffer,
303 &intel_obj->Base);
304 _mesa_free(intel_obj->sys_buffer);
305 intel_obj->sys_buffer = NULL;
306 }
307
308 return intel_obj->buffer;
309 }
310
311 void
312 intel_bufferobj_init(struct intel_context *intel)
313 {
314 GLcontext *ctx = &intel->ctx;
315
316 ctx->Driver.NewBufferObject = intel_bufferobj_alloc;
317 ctx->Driver.DeleteBuffer = intel_bufferobj_free;
318 ctx->Driver.BufferData = intel_bufferobj_data;
319 ctx->Driver.BufferSubData = intel_bufferobj_subdata;
320 ctx->Driver.GetBufferSubData = intel_bufferobj_get_subdata;
321 ctx->Driver.MapBuffer = intel_bufferobj_map;
322 ctx->Driver.UnmapBuffer = intel_bufferobj_unmap;
323 }