fix compiler warnings
[mesa.git] / src / mesa / drivers / dri / i915 / intel_batchbuffer.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 <stdio.h>
30 #include <errno.h>
31
32 #include "mtypes.h"
33 #include "context.h"
34 #include "enums.h"
35 #include "vblank.h"
36
37 #include "intel_reg.h"
38 #include "intel_batchbuffer.h"
39 #include "intel_context.h"
40
41
42
43
44 /* ================================================================
45 * Performance monitoring functions
46 */
47
48 static void intel_fill_box( intelContextPtr intel,
49 GLshort x, GLshort y,
50 GLshort w, GLshort h,
51 GLubyte r, GLubyte g, GLubyte b )
52 {
53 x += intel->drawX;
54 y += intel->drawY;
55
56 if (x >= 0 && y >= 0 &&
57 x+w < intel->intelScreen->width &&
58 y+h < intel->intelScreen->height)
59 intelEmitFillBlitLocked( intel,
60 intel->intelScreen->cpp,
61 intel->intelScreen->back.pitch,
62 intel->intelScreen->back.offset,
63 x, y, w, h,
64 INTEL_PACKCOLOR(intel->intelScreen->fbFormat,
65 r,g,b,0xff));
66 }
67
68 static void intel_draw_performance_boxes( intelContextPtr intel )
69 {
70 /* Purple box for page flipping
71 */
72 if ( intel->perf_boxes & I830_BOX_FLIP )
73 intel_fill_box( intel, 4, 4, 8, 8, 255, 0, 255 );
74
75 /* Red box if we have to wait for idle at any point
76 */
77 if ( intel->perf_boxes & I830_BOX_WAIT )
78 intel_fill_box( intel, 16, 4, 8, 8, 255, 0, 0 );
79
80 /* Blue box: lost context?
81 */
82 if ( intel->perf_boxes & I830_BOX_LOST_CONTEXT )
83 intel_fill_box( intel, 28, 4, 8, 8, 0, 0, 255 );
84
85 /* Yellow box for texture swaps
86 */
87 if ( intel->perf_boxes & I830_BOX_TEXTURE_LOAD )
88 intel_fill_box( intel, 40, 4, 8, 8, 255, 255, 0 );
89
90 /* Green box if hardware never idles (as far as we can tell)
91 */
92 if ( !(intel->perf_boxes & I830_BOX_RING_EMPTY) )
93 intel_fill_box( intel, 64, 4, 8, 8, 0, 255, 0 );
94
95
96 /* Draw bars indicating number of buffers allocated
97 * (not a great measure, easily confused)
98 */
99 #if 0
100 if (intel->dma_used) {
101 int bar = intel->dma_used / 10240;
102 if (bar > 100) bar = 100;
103 if (bar < 1) bar = 1;
104 intel_fill_box( intel, 4, 16, bar, 4, 196, 128, 128 );
105 intel->dma_used = 0;
106 }
107 #endif
108
109 intel->perf_boxes = 0;
110 }
111
112
113
114
115
116
117 static int bad_prim_vertex_nr( int primitive, int nr )
118 {
119 switch (primitive & PRIM3D_MASK) {
120 case PRIM3D_POINTLIST:
121 return nr < 1;
122 case PRIM3D_LINELIST:
123 return (nr & 1) || nr == 0;
124 case PRIM3D_LINESTRIP:
125 return nr < 2;
126 case PRIM3D_TRILIST:
127 case PRIM3D_RECTLIST:
128 return nr % 3 || nr == 0;
129 case PRIM3D_POLY:
130 case PRIM3D_TRIFAN:
131 case PRIM3D_TRISTRIP:
132 case PRIM3D_TRISTRIP_RVRSE:
133 return nr < 3;
134 default:
135 return 1;
136 }
137 }
138
139 static void intel_flush_inline_primitive( GLcontext *ctx )
140 {
141 intelContextPtr intel = INTEL_CONTEXT( ctx );
142 GLuint used = intel->batch.ptr - intel->prim.start_ptr;
143 GLuint vertcount;
144
145 assert(intel->prim.primitive != ~0);
146
147 if (1) {
148 /* Check vertex size against the vertex we're specifying to
149 * hardware. If it's wrong, ditch the primitive.
150 */
151 if (!intel->vtbl.check_vertex_size( intel, intel->vertex_size ))
152 goto do_discard;
153
154 vertcount = (used - 4)/ (intel->vertex_size * 4);
155
156 if (!vertcount)
157 goto do_discard;
158
159 if (vertcount * intel->vertex_size * 4 != used - 4) {
160 fprintf(stderr, "vertex size confusion %d %d\n", used,
161 intel->vertex_size * vertcount * 4);
162 goto do_discard;
163 }
164
165 if (bad_prim_vertex_nr( intel->prim.primitive, vertcount )) {
166 fprintf(stderr, "bad_prim_vertex_nr %x %d\n", intel->prim.primitive,
167 vertcount);
168 goto do_discard;
169 }
170 }
171
172 if (used < 8)
173 goto do_discard;
174
175 *(int *)intel->prim.start_ptr = (_3DPRIMITIVE |
176 intel->prim.primitive |
177 (used/4-2));
178
179 goto finished;
180
181 do_discard:
182 intel->batch.ptr -= used;
183 intel->batch.space += used;
184 assert(intel->batch.space >= 0);
185
186 finished:
187 intel->prim.primitive = ~0;
188 intel->prim.start_ptr = 0;
189 intel->prim.flush = 0;
190 }
191
192
193 /* Emit a primitive referencing vertices in a vertex buffer.
194 */
195 void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim )
196 {
197 BATCH_LOCALS;
198
199 if (0)
200 fprintf(stderr, "%s %x\n", __FUNCTION__, prim);
201
202
203 /* Finish any in-progress primitive:
204 */
205 INTEL_FIREVERTICES( intel );
206
207 /* Emit outstanding state:
208 */
209 intel->vtbl.emit_state( intel );
210
211 /* Make sure there is some space in this buffer:
212 */
213 if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space) {
214 intelFlushBatch(intel, GL_TRUE);
215 intel->vtbl.emit_state( intel );
216 }
217
218 #if 1
219 if (((unsigned long)intel->batch.ptr) & 0x4) {
220 BEGIN_BATCH(1);
221 OUT_BATCH(0);
222 ADVANCE_BATCH();
223 }
224 #endif
225
226 /* Emit a slot which will be filled with the inline primitive
227 * command later.
228 */
229 BEGIN_BATCH(2);
230 OUT_BATCH( 0 );
231
232 intel->prim.start_ptr = batch_ptr;
233 intel->prim.primitive = prim;
234 intel->prim.flush = intel_flush_inline_primitive;
235 intel->batch.contains_geometry = 1;
236
237 OUT_BATCH( 0 );
238 ADVANCE_BATCH();
239 }
240
241
242 void intelRestartInlinePrimitive( intelContextPtr intel )
243 {
244 GLuint prim = intel->prim.primitive;
245
246 intel_flush_inline_primitive( &intel->ctx );
247 if (1) intelFlushBatch(intel, GL_TRUE); /* GL_TRUE - is critical */
248 intelStartInlinePrimitive( intel, prim );
249 }
250
251
252
253 void intelWrapInlinePrimitive( intelContextPtr intel )
254 {
255 GLuint prim = intel->prim.primitive;
256
257 if (0)
258 fprintf(stderr, "%s\n", __FUNCTION__);
259 intel_flush_inline_primitive( &intel->ctx );
260 intelFlushBatch(intel, GL_TRUE);
261 intelStartInlinePrimitive( intel, prim );
262 }
263
264
265 /* Emit a primitive with space for inline vertices.
266 */
267 GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
268 int primitive,
269 int dwords,
270 int vertex_size )
271 {
272 GLuint *tmp = 0;
273 BATCH_LOCALS;
274
275 if (0)
276 fprintf(stderr, "%s 0x%x %d\n", __FUNCTION__, primitive, dwords);
277
278 /* Emit outstanding state:
279 */
280 intel->vtbl.emit_state( intel );
281
282 if ((1+dwords)*4 >= intel->batch.space) {
283 intelFlushBatch(intel, GL_TRUE);
284 intel->vtbl.emit_state( intel );
285 }
286
287
288 if (1) {
289 int used = dwords * 4;
290 int vertcount;
291
292 /* Check vertex size against the vertex we're specifying to
293 * hardware. If it's wrong, ditch the primitive.
294 */
295 if (!intel->vtbl.check_vertex_size( intel, vertex_size ))
296 goto do_discard;
297
298 vertcount = dwords / vertex_size;
299
300 if (dwords % vertex_size) {
301 fprintf(stderr, "did not request a whole number of vertices\n");
302 goto do_discard;
303 }
304
305 if (bad_prim_vertex_nr( primitive, vertcount )) {
306 fprintf(stderr, "bad_prim_vertex_nr %x %d\n", primitive, vertcount);
307 goto do_discard;
308 }
309
310 if (used < 8)
311 goto do_discard;
312 }
313
314 /* Emit 3D_PRIMITIVE commands:
315 */
316 BEGIN_BATCH(1 + dwords);
317 OUT_BATCH( _3DPRIMITIVE |
318 primitive |
319 (dwords-1) );
320
321 tmp = (GLuint *)batch_ptr;
322 batch_ptr += dwords * 4;
323
324 ADVANCE_BATCH();
325
326 intel->batch.contains_geometry = 1;
327
328 do_discard:
329 return tmp;
330 }
331
332
333 static void intelWaitForFrameCompletion( intelContextPtr intel )
334 {
335 drm_i915_sarea_t *sarea = (drm_i915_sarea_t *)intel->sarea;
336
337 if (intel->do_irqs) {
338 if (intelGetLastFrame(intel) < sarea->last_dispatch) {
339 if (!intel->irqsEmitted) {
340 while (intelGetLastFrame (intel) < sarea->last_dispatch)
341 ;
342 }
343 else {
344 intelWaitIrq( intel, intel->alloc.irq_emitted );
345 }
346 intel->irqsEmitted = 10;
347 }
348
349 if (intel->irqsEmitted) {
350 LOCK_HARDWARE( intel );
351 intelEmitIrqLocked( intel );
352 intel->irqsEmitted--;
353 UNLOCK_HARDWARE( intel );
354 }
355 }
356 else {
357 while (intelGetLastFrame (intel) < sarea->last_dispatch) {
358 if (intel->do_usleeps)
359 DO_USLEEP( 1 );
360 }
361 }
362 }
363
364 /*
365 * Copy the back buffer to the front buffer.
366 */
367 void intelCopyBuffer( const __DRIdrawablePrivate *dPriv,
368 const drm_clip_rect_t *rect)
369 {
370 intelContextPtr intel;
371 const intelScreenPrivate *intelScreen;
372 GLboolean missed_target;
373 int64_t ust;
374
375 if (0)
376 fprintf(stderr, "%s\n", __FUNCTION__);
377
378 assert(dPriv);
379 assert(dPriv->driContextPriv);
380 assert(dPriv->driContextPriv->driverPrivate);
381
382 intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
383
384 intelFlush( &intel->ctx );
385
386 intelScreen = intel->intelScreen;
387
388 if (!rect && !intel->swap_scheduled && intelScreen->drmMinor >= 6 &&
389 !(intel->vblank_flags & VBLANK_FLAG_NO_IRQ) &&
390 intelScreen->current_rotation == 0) {
391 unsigned int interval = driGetVBlankInterval(dPriv, intel->vblank_flags);
392 unsigned int target;
393 drm_i915_vblank_swap_t swap;
394
395 swap.drawable = dPriv->hHWDrawable;
396 swap.seqtype = DRM_VBLANK_ABSOLUTE;
397 target = swap.sequence = intel->vbl_seq + interval;
398
399 if (intel->vblank_flags & VBLANK_FLAG_SYNC) {
400 swap.seqtype |= DRM_VBLANK_NEXTONMISS;
401 } else if (interval == 0) {
402 goto noschedule;
403 }
404
405 if ( intel->vblank_flags & VBLANK_FLAG_SECONDARY ) {
406 swap.seqtype |= DRM_VBLANK_SECONDARY;
407 }
408
409 if (!drmCommandWriteRead(intel->driFd, DRM_I915_VBLANK_SWAP, &swap,
410 sizeof(swap))) {
411 intel->swap_scheduled = 1;
412 intel->vbl_seq = swap.sequence;
413 swap.sequence -= target;
414 missed_target = swap.sequence > 0 && swap.sequence <= (1 << 23);
415 }
416 } else {
417 intel->swap_scheduled = 0;
418 }
419 noschedule:
420
421 if (!intel->swap_scheduled) {
422 intelWaitForFrameCompletion( intel );
423 LOCK_HARDWARE( intel );
424
425 if (!rect)
426 {
427 UNLOCK_HARDWARE( intel );
428 driWaitForVBlank( dPriv, &intel->vbl_seq, intel->vblank_flags, & missed_target );
429 LOCK_HARDWARE( intel );
430 }
431 {
432 const intelScreenPrivate *intelScreen = intel->intelScreen;
433 const __DRIdrawablePrivate *dPriv = intel->driDrawable;
434 const int nbox = dPriv->numClipRects;
435 const drm_clip_rect_t *pbox = dPriv->pClipRects;
436 drm_clip_rect_t box;
437 const int cpp = intelScreen->cpp;
438 const int pitch = intelScreen->front.pitch; /* in bytes */
439 int i;
440 GLuint CMD, BR13;
441 BATCH_LOCALS;
442
443 switch(cpp) {
444 case 2:
445 BR13 = (pitch) | (0xCC << 16) | (1<<24);
446 CMD = XY_SRC_COPY_BLT_CMD;
447 break;
448 case 4:
449 BR13 = (pitch) | (0xCC << 16) | (1<<24) | (1<<25);
450 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
451 XY_SRC_COPY_BLT_WRITE_RGB);
452 break;
453 default:
454 BR13 = (pitch) | (0xCC << 16) | (1<<24);
455 CMD = XY_SRC_COPY_BLT_CMD;
456 break;
457 }
458
459 if (0)
460 intel_draw_performance_boxes( intel );
461
462 for (i = 0 ; i < nbox; i++, pbox++)
463 {
464 if (pbox->x1 > pbox->x2 ||
465 pbox->y1 > pbox->y2 ||
466 pbox->x2 > intelScreen->width ||
467 pbox->y2 > intelScreen->height) {
468 _mesa_warning(&intel->ctx, "Bad cliprect in intelCopyBuffer()");
469 continue;
470 }
471
472 box = *pbox;
473
474 if (rect)
475 {
476 if (rect->x1 > box.x1)
477 box.x1 = rect->x1;
478 if (rect->y1 > box.y1)
479 box.y1 = rect->y1;
480 if (rect->x2 < box.x2)
481 box.x2 = rect->x2;
482 if (rect->y2 < box.y2)
483 box.y2 = rect->y2;
484
485 if (box.x1 > box.x2 || box.y1 > box.y2)
486 continue;
487 }
488
489 BEGIN_BATCH( 8);
490 OUT_BATCH( CMD );
491 OUT_BATCH( BR13 );
492 OUT_BATCH( (box.y1 << 16) | box.x1 );
493 OUT_BATCH( (box.y2 << 16) | box.x2 );
494
495 if (intel->sarea->pf_current_page == 0)
496 OUT_BATCH( intelScreen->front.offset );
497 else
498 OUT_BATCH( intelScreen->back.offset );
499
500 OUT_BATCH( (box.y1 << 16) | box.x1 );
501 OUT_BATCH( BR13 & 0xffff );
502
503 if (intel->sarea->pf_current_page == 0)
504 OUT_BATCH( intelScreen->back.offset );
505 else
506 OUT_BATCH( intelScreen->front.offset );
507
508 ADVANCE_BATCH();
509 }
510 }
511 intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE );
512 UNLOCK_HARDWARE( intel );
513 }
514
515 if (!rect)
516 {
517 intel->swap_count++;
518 (*dri_interface->getUST)(&ust);
519 if (missed_target) {
520 intel->swap_missed_count++;
521 intel->swap_missed_ust = ust - intel->swap_ust;
522 }
523
524 intel->swap_ust = ust;
525 }
526 }
527
528
529
530
531 void intelEmitFillBlitLocked( intelContextPtr intel,
532 GLuint cpp,
533 GLshort dst_pitch, /* in bytes */
534 GLuint dst_offset,
535 GLshort x, GLshort y,
536 GLshort w, GLshort h,
537 GLuint color )
538 {
539 GLuint BR13, CMD;
540 BATCH_LOCALS;
541
542 switch(cpp) {
543 case 1:
544 case 2:
545 case 3:
546 BR13 = dst_pitch | (0xF0 << 16) | (1<<24);
547 CMD = XY_COLOR_BLT_CMD;
548 break;
549 case 4:
550 BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25);
551 CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
552 XY_COLOR_BLT_WRITE_RGB);
553 break;
554 default:
555 return;
556 }
557
558 BEGIN_BATCH( 6);
559 OUT_BATCH( CMD );
560 OUT_BATCH( BR13 );
561 OUT_BATCH( (y << 16) | x );
562 OUT_BATCH( ((y+h) << 16) | (x+w) );
563 OUT_BATCH( dst_offset );
564 OUT_BATCH( color );
565 ADVANCE_BATCH();
566 }
567
568
569 /* Copy BitBlt
570 */
571 void intelEmitCopyBlitLocked( intelContextPtr intel,
572 GLuint cpp,
573 GLshort src_pitch,
574 GLuint src_offset,
575 GLshort dst_pitch,
576 GLuint dst_offset,
577 GLshort src_x, GLshort src_y,
578 GLshort dst_x, GLshort dst_y,
579 GLshort w, GLshort h )
580 {
581 GLuint CMD, BR13;
582 int dst_y2 = dst_y + h;
583 int dst_x2 = dst_x + w;
584 BATCH_LOCALS;
585
586 src_pitch *= cpp;
587 dst_pitch *= cpp;
588
589 switch(cpp) {
590 case 1:
591 case 2:
592 case 3:
593 BR13 = dst_pitch | (0xCC << 16) | (1<<24);
594 CMD = XY_SRC_COPY_BLT_CMD;
595 break;
596 case 4:
597 BR13 = dst_pitch | (0xCC << 16) | (1<<24) | (1<<25);
598 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
599 XY_SRC_COPY_BLT_WRITE_RGB);
600 break;
601 default:
602 return;
603 }
604
605 if (dst_y2 < dst_y ||
606 dst_x2 < dst_x) {
607 return;
608 }
609
610 BEGIN_BATCH( 12);
611 OUT_BATCH( CMD );
612 OUT_BATCH( BR13 );
613 OUT_BATCH( (dst_y << 16) | dst_x );
614 OUT_BATCH( (dst_y2 << 16) | dst_x2 );
615 OUT_BATCH( dst_offset );
616 OUT_BATCH( (src_y << 16) | src_x );
617 OUT_BATCH( src_pitch );
618 OUT_BATCH( src_offset );
619 ADVANCE_BATCH();
620 }
621
622
623
624 void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
625 GLint cx1, GLint cy1, GLint cw, GLint ch)
626 {
627 intelContextPtr intel = INTEL_CONTEXT( ctx );
628 intelScreenPrivate *intelScreen = intel->intelScreen;
629 GLuint clear_depth, clear_color;
630 GLint cx, cy;
631 GLint pitch;
632 GLint cpp = intelScreen->cpp;
633 GLint i;
634 GLuint BR13, CMD, D_CMD;
635 BATCH_LOCALS;
636
637 intelFlush( &intel->ctx );
638 LOCK_HARDWARE( intel );
639
640 pitch = intelScreen->front.pitch;
641
642 clear_color = intel->ClearColor;
643 clear_depth = 0;
644
645 if (flags & BUFFER_BIT_DEPTH) {
646 clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
647 }
648
649 if (flags & BUFFER_BIT_STENCIL) {
650 clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
651 }
652
653 switch(cpp) {
654 case 2:
655 BR13 = (0xF0 << 16) | (pitch) | (1<<24);
656 D_CMD = CMD = XY_COLOR_BLT_CMD;
657 break;
658 case 4:
659 BR13 = (0xF0 << 16) | (pitch) | (1<<24) | (1<<25);
660 CMD = (XY_COLOR_BLT_CMD |
661 XY_COLOR_BLT_WRITE_ALPHA |
662 XY_COLOR_BLT_WRITE_RGB);
663 D_CMD = XY_COLOR_BLT_CMD;
664 if (flags & BUFFER_BIT_DEPTH) D_CMD |= XY_COLOR_BLT_WRITE_RGB;
665 if (flags & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
666 break;
667 default:
668 BR13 = (0xF0 << 16) | (pitch) | (1<<24);
669 D_CMD = CMD = XY_COLOR_BLT_CMD;
670 break;
671 }
672
673 {
674 /* flip top to bottom */
675 cy = intel->driDrawable->h-cy1-ch;
676 cx = cx1 + intel->drawX;
677 cy += intel->drawY;
678
679 /* adjust for page flipping */
680 if ( intel->sarea->pf_current_page == 1 ) {
681 GLuint tmp = flags;
682
683 flags &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
684 if ( tmp & BUFFER_BIT_FRONT_LEFT ) flags |= BUFFER_BIT_BACK_LEFT;
685 if ( tmp & BUFFER_BIT_BACK_LEFT ) flags |= BUFFER_BIT_FRONT_LEFT;
686 }
687
688 for (i = 0 ; i < intel->numClipRects ; i++)
689 {
690 drm_clip_rect_t *box = &intel->pClipRects[i];
691 drm_clip_rect_t b;
692
693 if (!all) {
694 GLint x = box->x1;
695 GLint y = box->y1;
696 GLint w = box->x2 - x;
697 GLint h = box->y2 - y;
698
699 if (x < cx) w -= cx - x, x = cx;
700 if (y < cy) h -= cy - y, y = cy;
701 if (x + w > cx + cw) w = cx + cw - x;
702 if (y + h > cy + ch) h = cy + ch - y;
703 if (w <= 0) continue;
704 if (h <= 0) continue;
705
706 b.x1 = x;
707 b.y1 = y;
708 b.x2 = x + w;
709 b.y2 = y + h;
710 } else {
711 b = *box;
712 }
713
714
715 if (b.x1 > b.x2 ||
716 b.y1 > b.y2 ||
717 b.x2 > intelScreen->width ||
718 b.y2 > intelScreen->height)
719 continue;
720
721 if ( flags & BUFFER_BIT_FRONT_LEFT ) {
722 BEGIN_BATCH( 6);
723 OUT_BATCH( CMD );
724 OUT_BATCH( BR13 );
725 OUT_BATCH( (b.y1 << 16) | b.x1 );
726 OUT_BATCH( (b.y2 << 16) | b.x2 );
727 OUT_BATCH( intelScreen->front.offset );
728 OUT_BATCH( clear_color );
729 ADVANCE_BATCH();
730 }
731
732 if ( flags & BUFFER_BIT_BACK_LEFT ) {
733 BEGIN_BATCH( 6);
734 OUT_BATCH( CMD );
735 OUT_BATCH( BR13 );
736 OUT_BATCH( (b.y1 << 16) | b.x1 );
737 OUT_BATCH( (b.y2 << 16) | b.x2 );
738 OUT_BATCH( intelScreen->back.offset );
739 OUT_BATCH( clear_color );
740 ADVANCE_BATCH();
741 }
742
743 if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) {
744 BEGIN_BATCH( 6);
745 OUT_BATCH( D_CMD );
746 OUT_BATCH( BR13 );
747 OUT_BATCH( (b.y1 << 16) | b.x1 );
748 OUT_BATCH( (b.y2 << 16) | b.x2 );
749 OUT_BATCH( intelScreen->depth.offset );
750 OUT_BATCH( clear_depth );
751 ADVANCE_BATCH();
752 }
753 }
754 }
755 intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
756 UNLOCK_HARDWARE( intel );
757 }
758
759
760
761
762 void intelDestroyBatchBuffer( GLcontext *ctx )
763 {
764 intelContextPtr intel = INTEL_CONTEXT(ctx);
765
766 if (intel->alloc.offset) {
767 intelFreeAGP( intel, intel->alloc.ptr );
768 intel->alloc.ptr = NULL;
769 intel->alloc.offset = 0;
770 }
771 else if (intel->alloc.ptr) {
772 free(intel->alloc.ptr);
773 intel->alloc.ptr = NULL;
774 }
775
776 memset(&intel->batch, 0, sizeof(intel->batch));
777 }
778
779
780 void intelInitBatchBuffer( GLcontext *ctx )
781 {
782 intelContextPtr intel = INTEL_CONTEXT(ctx);
783
784 /* This path isn't really safe with rotate:
785 */
786 if (getenv("INTEL_BATCH") && intel->intelScreen->allow_batchbuffer) {
787 switch (intel->intelScreen->deviceID) {
788 case PCI_CHIP_I865_G:
789 /* HW bug? Seems to crash if batchbuffer crosses 4k boundary.
790 */
791 intel->alloc.size = 8 * 1024;
792 break;
793 default:
794 /* This is the smallest amount of memory the kernel deals with.
795 * We'd ideally like to make this smaller.
796 */
797 intel->alloc.size = 1 << intel->intelScreen->logTextureGranularity;
798 break;
799 }
800
801 intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size );
802 if (intel->alloc.ptr)
803 intel->alloc.offset =
804 intelAgpOffsetFromVirtual( intel, intel->alloc.ptr );
805 else
806 intel->alloc.offset = 0; /* OK? */
807 }
808
809 /* The default is now to use a local buffer and pass that to the
810 * kernel. This is also a fallback if allocation fails on the
811 * above path:
812 */
813 if (!intel->alloc.ptr) {
814 intel->alloc.size = 8 * 1024;
815 intel->alloc.ptr = malloc( intel->alloc.size );
816 intel->alloc.offset = 0;
817 }
818
819 assert(intel->alloc.ptr);
820 }