Merge branch 'master' of git+ssh://znh@git.freedesktop.org/git/mesa/mesa
[mesa.git] / src / mesa / drivers / dri / i965 / brw_draw.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 #include <stdlib.h>
29
30 #include "glheader.h"
31 #include "context.h"
32 #include "state.h"
33 #include "api_validate.h"
34 #include "enums.h"
35
36 #include "brw_draw.h"
37 #include "brw_defines.h"
38 #include "brw_attrib.h"
39 #include "brw_context.h"
40 #include "brw_aub.h"
41 #include "brw_state.h"
42 #include "brw_fallback.h"
43
44 #include "intel_ioctl.h"
45 #include "intel_batchbuffer.h"
46 #include "intel_buffer_objects.h"
47
48
49
50
51
52
53 static GLuint hw_prim[GL_POLYGON+1] = {
54 _3DPRIM_POINTLIST,
55 _3DPRIM_LINELIST,
56 _3DPRIM_LINELOOP,
57 _3DPRIM_LINESTRIP,
58 _3DPRIM_TRILIST,
59 _3DPRIM_TRISTRIP,
60 _3DPRIM_TRIFAN,
61 _3DPRIM_QUADLIST,
62 _3DPRIM_QUADSTRIP,
63 _3DPRIM_POLYGON
64 };
65
66
67 static const GLenum reduced_prim[GL_POLYGON+1] = {
68 GL_POINTS,
69 GL_LINES,
70 GL_LINES,
71 GL_LINES,
72 GL_TRIANGLES,
73 GL_TRIANGLES,
74 GL_TRIANGLES,
75 GL_TRIANGLES,
76 GL_TRIANGLES,
77 GL_TRIANGLES
78 };
79
80
81 /* When the primitive changes, set a state bit and re-validate. Not
82 * the nicest and would rather deal with this by having all the
83 * programs be immune to the active primitive (ie. cope with all
84 * possibilities). That may not be realistic however.
85 */
86 static GLuint brw_set_prim(struct brw_context *brw, GLenum prim)
87 {
88 if (INTEL_DEBUG & DEBUG_PRIMS)
89 _mesa_printf("PRIM: %s\n", _mesa_lookup_enum_by_nr(prim));
90
91 /* Slight optimization to avoid the GS program when not needed:
92 */
93 if (prim == GL_QUAD_STRIP &&
94 brw->attribs.Light->ShadeModel != GL_FLAT &&
95 brw->attribs.Polygon->FrontMode == GL_FILL &&
96 brw->attribs.Polygon->BackMode == GL_FILL)
97 prim = GL_TRIANGLE_STRIP;
98
99 if (prim != brw->primitive) {
100 brw->primitive = prim;
101 brw->state.dirty.brw |= BRW_NEW_PRIMITIVE;
102
103 if (reduced_prim[prim] != brw->intel.reduced_primitive) {
104 brw->intel.reduced_primitive = reduced_prim[prim];
105 brw->state.dirty.brw |= BRW_NEW_REDUCED_PRIMITIVE;
106 }
107
108 brw_validate_state(brw);
109 }
110
111 return hw_prim[prim];
112 }
113
114
115 static GLuint trim(GLenum prim, GLuint length)
116 {
117 if (prim == GL_QUAD_STRIP)
118 return length > 3 ? (length - length % 2) : 0;
119 else if (prim == GL_QUADS)
120 return length - length % 4;
121 else
122 return length;
123 }
124
125
126 static void brw_emit_cliprect( struct brw_context *brw,
127 const drm_clip_rect_t *rect )
128 {
129 struct brw_drawrect bdr;
130
131 bdr.header.opcode = CMD_DRAW_RECT;
132 bdr.header.length = sizeof(bdr)/4 - 2;
133 bdr.xmin = rect->x1;
134 bdr.xmax = rect->x2 - 1;
135 bdr.ymin = rect->y1;
136 bdr.ymax = rect->y2 - 1;
137 bdr.xorg = brw->intel.drawX;
138 bdr.yorg = brw->intel.drawY;
139
140 intel_batchbuffer_data( brw->intel.batch, &bdr, sizeof(bdr),
141 INTEL_BATCH_NO_CLIPRECTS);
142 }
143
144
145 static void brw_emit_prim( struct brw_context *brw,
146 const struct brw_draw_prim *prim )
147
148 {
149 struct brw_3d_primitive prim_packet;
150
151 if (INTEL_DEBUG & DEBUG_PRIMS)
152 _mesa_printf("PRIM: %s %d %d\n", _mesa_lookup_enum_by_nr(prim->mode),
153 prim->start, prim->count);
154
155 prim_packet.header.opcode = CMD_3D_PRIM;
156 prim_packet.header.length = sizeof(prim_packet)/4 - 2;
157 prim_packet.header.pad = 0;
158 prim_packet.header.topology = brw_set_prim(brw, prim->mode);
159 prim_packet.header.indexed = prim->indexed;
160
161 prim_packet.verts_per_instance = trim(prim->mode, prim->count);
162 prim_packet.start_vert_location = prim->start;
163 prim_packet.instance_count = 1;
164 prim_packet.start_instance_location = 0;
165 prim_packet.base_vert_location = 0;
166
167 if (prim_packet.verts_per_instance) {
168 intel_batchbuffer_data( brw->intel.batch, &prim_packet, sizeof(prim_packet),
169 INTEL_BATCH_NO_CLIPRECTS);
170 }
171 }
172
173
174
175 static void update_current_size( struct gl_client_array *array)
176 {
177 const GLfloat *ptr = (const GLfloat *)array->Ptr;
178
179 assert(array->StrideB == 0);
180 assert(array->Type == GL_FLOAT || array->Type == GL_UNSIGNED_BYTE);
181
182 if (ptr[3] != 1.0)
183 array->Size = 4;
184 else if (ptr[2] != 0.0)
185 array->Size = 3;
186 else if (ptr[1] != 0.0)
187 array->Size = 2;
188 else
189 array->Size = 1;
190 }
191
192
193
194 /* Fill in any gaps in passed arrays with pointers to current
195 * attributes:
196 */
197 static void brw_merge_inputs( struct brw_context *brw,
198 const struct gl_client_array *arrays[])
199 {
200 struct gl_client_array *current_values = brw->vb.current_values;
201 struct brw_vertex_element *inputs = brw->vb.inputs;
202 struct brw_vertex_info old = brw->vb.info;
203 GLuint i;
204
205 memset(inputs, 0, sizeof(*inputs));
206 memset(&brw->vb.info, 0, sizeof(brw->vb.info));
207
208 for (i = 0; i < BRW_ATTRIB_MAX; i++) {
209 if (arrays[i] && arrays[i]->Enabled)
210 {
211 brw->vb.inputs[i].glarray = arrays[i];
212 brw->vb.info.varying |= (GLuint64EXT) 1 << i;
213 }
214 else
215 {
216 brw->vb.inputs[i].glarray = &current_values[i];
217 update_current_size(&current_values[i]);
218 }
219
220 brw->vb.info.sizes[i/16] |= (inputs[i].glarray->Size - 1) << ((i%16) * 2);
221 }
222
223 /* Raise statechanges if input sizes and varying have changed:
224 */
225 if (memcmp(brw->vb.info.sizes, old.sizes, sizeof(old.sizes)) != 0)
226 brw->state.dirty.brw |= BRW_NEW_INPUT_DIMENSIONS;
227
228 if (brw->vb.info.varying != old.varying)
229 brw->state.dirty.brw |= BRW_NEW_INPUT_VARYING;
230 }
231
232 static GLboolean check_fallbacks( struct brw_context *brw,
233 const struct brw_draw_prim *prim,
234 GLuint nr_prims )
235 {
236 GLuint i;
237
238 if (!brw->intel.strict_conformance)
239 return GL_FALSE;
240
241 if (brw->attribs.Polygon->SmoothFlag) {
242 for (i = 0; i < nr_prims; i++)
243 if (reduced_prim[prim[i].mode] == GL_TRIANGLES)
244 return GL_TRUE;
245 }
246
247 /* BRW hardware will do AA lines, but they are non-conformant it
248 * seems. TBD whether we keep this fallback:
249 */
250 if (brw->attribs.Line->SmoothFlag) {
251 for (i = 0; i < nr_prims; i++)
252 if (reduced_prim[prim[i].mode] == GL_LINES)
253 return GL_TRUE;
254 }
255
256 /* Stipple -- these fallbacks could be resolved with a little
257 * bit of work?
258 */
259 if (brw->attribs.Line->StippleFlag) {
260 for (i = 0; i < nr_prims; i++) {
261 /* GS doesn't get enough information to know when to reset
262 * the stipple counter?!?
263 */
264 if (prim[i].mode == GL_LINE_LOOP)
265 return GL_TRUE;
266
267 if (prim[i].mode == GL_POLYGON &&
268 (brw->attribs.Polygon->FrontMode == GL_LINE ||
269 brw->attribs.Polygon->BackMode == GL_LINE))
270 return GL_TRUE;
271 }
272 }
273
274
275 if (brw->attribs.Point->SmoothFlag) {
276 for (i = 0; i < nr_prims; i++)
277 if (prim[i].mode == GL_POINTS)
278 return GL_TRUE;
279 }
280
281 return GL_FALSE;
282 }
283
284
285 static GLboolean brw_try_draw_prims( GLcontext *ctx,
286 const struct gl_client_array *arrays[],
287 const struct brw_draw_prim *prim,
288 GLuint nr_prims,
289 const struct brw_draw_index_buffer *ib,
290 GLuint min_index,
291 GLuint max_index,
292 GLuint flags )
293 {
294 struct intel_context *intel = intel_context(ctx);
295 struct brw_context *brw = brw_context(ctx);
296 GLboolean retval = GL_FALSE;
297 GLuint i, j;
298
299 if (ctx->NewState)
300 _mesa_update_state( ctx );
301
302 /* Bind all inputs, derive varying and size information:
303 */
304 brw_merge_inputs( brw, arrays );
305
306 /* Have to validate state quite late. Will rebuild tnl_program,
307 * which depends on varying information.
308 *
309 * Note this is where brw->vs->prog_data.inputs_read is calculated,
310 * so can't access it earlier.
311 */
312
313 LOCK_HARDWARE(intel);
314
315 if (brw->intel.numClipRects == 0) {
316 assert(intel->batch->ptr == intel->batch->map + intel->batch->offset);
317 UNLOCK_HARDWARE(intel);
318 return GL_TRUE;
319 }
320
321 {
322 assert(intel->locked);
323
324
325
326 /* Set the first primitive early, ahead of validate_state:
327 */
328 brw_set_prim(brw, prim[0].mode);
329
330 /* XXX: Need to separate validate and upload of state.
331 */
332 brw_validate_state( brw );
333
334 /* Various fallback checks:
335 */
336 if (brw->intel.Fallback)
337 goto out;
338
339 if (check_fallbacks( brw, prim, nr_prims ))
340 goto out;
341
342 /* Upload index, vertex data:
343 */
344 if (ib)
345 brw_upload_indices( brw, ib );
346
347 if (!brw_upload_vertices( brw, min_index, max_index)) {
348 goto out;
349 }
350
351 /* For single cliprect, state is already emitted:
352 */
353 if (brw->intel.numClipRects == 1) {
354 for (i = 0; i < nr_prims; i++) {
355 brw_emit_prim(brw, &prim[i]);
356 }
357 }
358 else {
359 /* Otherwise, explicitly do the cliprects at this point:
360 */
361 for (j = 0; j < brw->intel.numClipRects; j++) {
362 brw_emit_cliprect(brw, &brw->intel.pClipRects[j]);
363
364 /* Emit prims to batchbuffer:
365 */
366 for (i = 0; i < nr_prims; i++) {
367 brw_emit_prim(brw, &prim[i]);
368 }
369 }
370 }
371
372 intel->need_flush = GL_TRUE;
373 retval = GL_TRUE;
374 }
375
376 out:
377
378 /* Currently have to do this to synchronize with the map/unmap of
379 * the vertex buffer in brw_exec_api.c. Not sure if there is any
380 * way around this, as not every flush is due to a buffer filling
381 * up.
382 */
383 if (!intel_batchbuffer_flush( brw->intel.batch )) {
384 DBG("%s intel_batchbuffer_flush failed\n", __FUNCTION__);
385 retval = GL_FALSE;
386 }
387
388 if (retval && intel->thrashing) {
389 bmSetFence(intel);
390 }
391
392 /* Free any old data so it doesn't clog up texture memory - we
393 * won't be referencing it again.
394 */
395 while (brw->vb.upload.wrap != brw->vb.upload.buf) {
396 ctx->Driver.BufferData(ctx,
397 GL_ARRAY_BUFFER_ARB,
398 BRW_UPLOAD_INIT_SIZE,
399 NULL,
400 GL_DYNAMIC_DRAW_ARB,
401 brw->vb.upload.vbo[brw->vb.upload.wrap]);
402 brw->vb.upload.wrap++;
403 brw->vb.upload.wrap %= BRW_NR_UPLOAD_BUFS;
404 }
405
406 UNLOCK_HARDWARE(intel);
407
408 if (!retval)
409 DBG("%s failed\n", __FUNCTION__);
410
411 return retval;
412 }
413
414
415 GLboolean brw_draw_prims( GLcontext *ctx,
416 const struct gl_client_array *arrays[],
417 const struct brw_draw_prim *prim,
418 GLuint nr_prims,
419 const struct brw_draw_index_buffer *ib,
420 GLuint min_index,
421 GLuint max_index,
422 GLuint flags )
423 {
424 struct intel_context *intel = intel_context(ctx);
425 GLboolean retval;
426
427 retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index, flags);
428
429
430 if (!retval && bmError(intel)) {
431
432 DBG("retrying\n");
433 /* This looks like out-of-memory but potentially we have
434 * situation where there is enough memory but it has become
435 * fragmented. Clear out all heaps and start from scratch by
436 * faking a contended lock event: (done elsewhere)
437 */
438
439 /* Then try a second time only to upload textures and draw the
440 * primitives:
441 */
442 retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index, flags);
443 }
444
445 if (intel->aub_file && (INTEL_DEBUG & DEBUG_SYNC)) {
446 intelFinish( &intel->ctx );
447 intel->aub_wrap = 1;
448 }
449
450
451 return retval;
452 }
453
454
455 static void brw_invalidate_vbo_cb( struct intel_context *intel, void *ptr )
456 {
457 /* nothing to do, we don't rely on the contents being preserved */
458 }
459
460
461 void brw_draw_init( struct brw_context *brw )
462 {
463 GLcontext *ctx = &brw->intel.ctx;
464 GLuint i;
465
466 brw->vb.upload.size = BRW_UPLOAD_INIT_SIZE;
467
468 for (i = 0; i < BRW_NR_UPLOAD_BUFS; i++) {
469 brw->vb.upload.vbo[i] = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB);
470
471 /* XXX: Set these to no-backing-store
472 */
473 bmBufferSetInvalidateCB(&brw->intel,
474 intel_bufferobj_buffer(intel_buffer_object(brw->vb.upload.vbo[i])),
475 brw_invalidate_vbo_cb,
476 &brw->intel,
477 GL_TRUE);
478
479 }
480
481 ctx->Driver.BufferData( ctx,
482 GL_ARRAY_BUFFER_ARB,
483 BRW_UPLOAD_INIT_SIZE,
484 NULL,
485 GL_DYNAMIC_DRAW_ARB,
486 brw->vb.upload.vbo[0] );
487
488
489 brw_init_current_values(ctx, brw->vb.current_values);
490 }
491
492 void brw_draw_destroy( struct brw_context *brw )
493 {
494 GLcontext *ctx = &brw->intel.ctx;
495 GLuint i;
496
497 for (i = 0; i < BRW_NR_UPLOAD_BUFS; i++)
498 ctx->Driver.DeleteBuffer(ctx, brw->vb.upload.vbo[i]);
499 }