OSDN Git Service

Fix writemasks on texture arb fp instructions.
[android-x86/external-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             UNLOCK_HARDWARE( intel ); 
345             intelWaitIrq( intel, intel->alloc.irq_emitted );    
346             LOCK_HARDWARE( intel ); 
347          }
348          intel->irqsEmitted = 10;
349       }
350
351       if (intel->irqsEmitted) {
352          intelEmitIrqLocked( intel );
353          intel->irqsEmitted--;
354       }
355    } 
356    else {
357       while (intelGetLastFrame (intel) < sarea->last_dispatch) {
358          UNLOCK_HARDWARE( intel ); 
359          if (intel->do_usleeps) 
360             DO_USLEEP( 1 );
361          LOCK_HARDWARE( intel ); 
362       }
363    }
364 }
365
366 /*
367  * Copy the back buffer to the front buffer. 
368  */
369 void intelCopyBuffer( const __DRIdrawablePrivate *dPriv,
370                       const drm_clip_rect_t      *rect)
371 {
372    intelContextPtr intel;
373    GLboolean   missed_target;
374    int64_t ust;
375
376    if (0)
377       fprintf(stderr, "%s\n", __FUNCTION__);
378
379    assert(dPriv);
380    assert(dPriv->driContextPriv);
381    assert(dPriv->driContextPriv->driverPrivate);
382
383    intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
384
385    intelFlush( &intel->ctx );
386    
387    intelWaitForFrameCompletion( intel );
388    LOCK_HARDWARE( intel );
389
390    if (!rect)
391    {
392        UNLOCK_HARDWARE( intel );
393        driWaitForVBlank( dPriv, &intel->vbl_seq, intel->vblank_flags, & missed_target );
394        LOCK_HARDWARE( intel );
395    }
396    {
397       const intelScreenPrivate *intelScreen = intel->intelScreen;
398       const __DRIdrawablePrivate *dPriv = intel->driDrawable;
399       const int nbox = dPriv->numClipRects;
400       const drm_clip_rect_t *pbox = dPriv->pClipRects;
401       drm_clip_rect_t box;
402       const int cpp = intelScreen->cpp;
403       const int pitch = intelScreen->front.pitch; /* in bytes */
404       int i;
405       GLuint CMD, BR13;
406       BATCH_LOCALS;
407
408       switch(cpp) {
409       case 2: 
410          BR13 = (pitch) | (0xCC << 16) | (1<<24);
411          CMD = XY_SRC_COPY_BLT_CMD;
412          break;
413       case 4:
414          BR13 = (pitch) | (0xCC << 16) | (1<<24) | (1<<25);
415          CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
416                 XY_SRC_COPY_BLT_WRITE_RGB);
417          break;
418       default:
419          BR13 = (pitch) | (0xCC << 16) | (1<<24);
420          CMD = XY_SRC_COPY_BLT_CMD;
421          break;
422       }
423    
424       if (0) 
425          intel_draw_performance_boxes( intel );
426
427       for (i = 0 ; i < nbox; i++, pbox++) 
428       {
429          if (pbox->x1 > pbox->x2 ||
430              pbox->y1 > pbox->y2 ||
431              pbox->x2 > intelScreen->width ||
432              pbox->y2 > intelScreen->height) {
433             _mesa_warning(&intel->ctx, "Bad cliprect in intelCopyBuffer()");
434             continue;
435          }
436
437          box = *pbox;
438
439          if (rect)
440          {
441              if (rect->x1 > box.x1)
442                  box.x1 = rect->x1;
443              if (rect->y1 > box.y1)
444                  box.y1 = rect->y1;
445              if (rect->x2 < box.x2)
446                  box.x2 = rect->x2;
447              if (rect->y2 < box.y2)
448                  box.y2 = rect->y2;
449
450              if (box.x1 > box.x2 || box.y1 > box.y2)
451                  continue;
452          }
453
454          BEGIN_BATCH( 8);
455          OUT_BATCH( CMD );
456          OUT_BATCH( BR13 );
457          OUT_BATCH( (box.y1 << 16) | box.x1 );
458          OUT_BATCH( (box.y2 << 16) | box.x2 );
459
460          if (intel->sarea->pf_current_page == 0) 
461             OUT_BATCH( intelScreen->front.offset );
462          else
463             OUT_BATCH( intelScreen->back.offset );                      
464
465          OUT_BATCH( (box.y1 << 16) | box.x1 );
466          OUT_BATCH( BR13 & 0xffff );
467
468          if (intel->sarea->pf_current_page == 0) 
469             OUT_BATCH( intelScreen->back.offset );                      
470          else
471             OUT_BATCH( intelScreen->front.offset );
472
473          ADVANCE_BATCH();
474       }
475    }
476    intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE );
477    UNLOCK_HARDWARE( intel );
478
479    if (!rect)
480    {
481        intel->swap_count++;
482        (*dri_interface->getUST)(&ust);
483        if (missed_target) {
484            intel->swap_missed_count++;
485            intel->swap_missed_ust = ust -  intel->swap_ust;
486        }
487    
488        intel->swap_ust = ust;
489    }
490 }
491
492
493
494
495 void intelEmitFillBlitLocked( intelContextPtr intel,
496                               GLuint cpp,
497                               GLshort dst_pitch,  /* in bytes */
498                               GLuint dst_offset,
499                               GLshort x, GLshort y, 
500                               GLshort w, GLshort h,
501                               GLuint color )
502 {
503    GLuint BR13, CMD;
504    BATCH_LOCALS;
505
506    switch(cpp) {
507    case 1: 
508    case 2: 
509    case 3: 
510       BR13 = dst_pitch | (0xF0 << 16) | (1<<24);
511       CMD = XY_COLOR_BLT_CMD;
512       break;
513    case 4:
514       BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25);
515       CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
516              XY_COLOR_BLT_WRITE_RGB);
517       break;
518    default:
519       return;
520    }
521
522    BEGIN_BATCH( 6);
523    OUT_BATCH( CMD );
524    OUT_BATCH( BR13 );
525    OUT_BATCH( (y << 16) | x );
526    OUT_BATCH( ((y+h) << 16) | (x+w) );
527    OUT_BATCH( dst_offset );
528    OUT_BATCH( color );
529    ADVANCE_BATCH();
530 }
531
532
533 /* Copy BitBlt
534  */
535 void intelEmitCopyBlitLocked( intelContextPtr intel,
536                               GLuint cpp,
537                               GLshort src_pitch,
538                               GLuint  src_offset,
539                               GLshort dst_pitch,
540                               GLuint  dst_offset,
541                               GLshort src_x, GLshort src_y,
542                               GLshort dst_x, GLshort dst_y,
543                               GLshort w, GLshort h )
544 {
545    GLuint CMD, BR13;
546    int dst_y2 = dst_y + h;
547    int dst_x2 = dst_x + w;
548    BATCH_LOCALS;
549
550    src_pitch *= cpp;
551    dst_pitch *= cpp;
552
553    switch(cpp) {
554    case 1: 
555    case 2: 
556    case 3: 
557       BR13 = dst_pitch | (0xCC << 16) | (1<<24);
558       CMD = XY_SRC_COPY_BLT_CMD;
559       break;
560    case 4:
561       BR13 = dst_pitch | (0xCC << 16) | (1<<24) | (1<<25);
562       CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
563              XY_SRC_COPY_BLT_WRITE_RGB);
564       break;
565    default:
566       return;
567    }
568
569    if (dst_y2 < dst_y ||
570        dst_x2 < dst_x) {
571       return;
572    }
573
574    BEGIN_BATCH( 12);
575    OUT_BATCH( CMD );
576    OUT_BATCH( BR13 );
577    OUT_BATCH( (dst_y << 16) | dst_x );
578    OUT_BATCH( (dst_y2 << 16) | dst_x2 );
579    OUT_BATCH( dst_offset );     
580    OUT_BATCH( (src_y << 16) | src_x );
581    OUT_BATCH( src_pitch );
582    OUT_BATCH( src_offset ); 
583    ADVANCE_BATCH();
584 }
585
586
587
588 void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
589                       GLint cx1, GLint cy1, GLint cw, GLint ch)
590 {
591    intelContextPtr intel = INTEL_CONTEXT( ctx );
592    intelScreenPrivate *intelScreen = intel->intelScreen;
593    GLuint clear_depth, clear_color;
594    GLint cx, cy;
595    GLint pitch;
596    GLint cpp = intelScreen->cpp;
597    GLint i;
598    GLuint BR13, CMD, D_CMD;
599    BATCH_LOCALS;
600
601    intelFlush( &intel->ctx );
602    LOCK_HARDWARE( intel );
603
604    pitch = intelScreen->front.pitch;
605
606    clear_color = intel->ClearColor;
607    clear_depth = 0;
608
609    if (flags & BUFFER_BIT_DEPTH) {
610       clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
611    }
612
613    if (flags & BUFFER_BIT_STENCIL) {
614       clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
615    }
616
617    switch(cpp) {
618    case 2: 
619       BR13 = (0xF0 << 16) | (pitch) | (1<<24);
620       D_CMD = CMD = XY_COLOR_BLT_CMD;
621       break;
622    case 4:
623       BR13 = (0xF0 << 16) | (pitch) | (1<<24) | (1<<25);
624       CMD = (XY_COLOR_BLT_CMD |
625              XY_COLOR_BLT_WRITE_ALPHA | 
626              XY_COLOR_BLT_WRITE_RGB);
627       D_CMD = XY_COLOR_BLT_CMD;
628       if (flags & BUFFER_BIT_DEPTH) D_CMD |= XY_COLOR_BLT_WRITE_RGB;
629       if (flags & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
630       break;
631    default:
632       BR13 = (0xF0 << 16) | (pitch) | (1<<24);
633       D_CMD = CMD = XY_COLOR_BLT_CMD;
634       break;
635    }
636
637    {
638       /* flip top to bottom */
639       cy = intel->driDrawable->h-cy1-ch;
640       cx = cx1 + intel->drawX;
641       cy += intel->drawY;
642
643       /* adjust for page flipping */
644       if ( intel->sarea->pf_current_page == 1 ) {
645          GLuint tmp = flags;
646
647          flags &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
648          if ( tmp & BUFFER_BIT_FRONT_LEFT ) flags |= BUFFER_BIT_BACK_LEFT;
649          if ( tmp & BUFFER_BIT_BACK_LEFT )  flags |= BUFFER_BIT_FRONT_LEFT;
650       }
651
652       for (i = 0 ; i < intel->numClipRects ; i++) 
653       {          
654          drm_clip_rect_t *box = &intel->pClipRects[i];   
655          drm_clip_rect_t b;
656
657          if (!all) {
658             GLint x = box->x1;
659             GLint y = box->y1;
660             GLint w = box->x2 - x;
661             GLint h = box->y2 - y;
662
663             if (x < cx) w -= cx - x, x = cx; 
664             if (y < cy) h -= cy - y, y = cy;
665             if (x + w > cx + cw) w = cx + cw - x;
666             if (y + h > cy + ch) h = cy + ch - y;
667             if (w <= 0) continue;
668             if (h <= 0) continue;
669
670             b.x1 = x;
671             b.y1 = y;
672             b.x2 = x + w;
673             b.y2 = y + h;      
674          } else {
675             b = *box;
676          }
677
678
679          if (b.x1 > b.x2 ||
680              b.y1 > b.y2 ||
681              b.x2 > intelScreen->width ||
682              b.y2 > intelScreen->height)
683             continue;
684
685          if ( flags & BUFFER_BIT_FRONT_LEFT ) {     
686             BEGIN_BATCH( 6);        
687             OUT_BATCH( CMD );
688             OUT_BATCH( BR13 );
689             OUT_BATCH( (b.y1 << 16) | b.x1 );
690             OUT_BATCH( (b.y2 << 16) | b.x2 );
691             OUT_BATCH( intelScreen->front.offset );
692             OUT_BATCH( clear_color );
693             ADVANCE_BATCH();
694          }
695
696          if ( flags & BUFFER_BIT_BACK_LEFT ) {
697             BEGIN_BATCH( 6); 
698             OUT_BATCH( CMD );
699             OUT_BATCH( BR13 );
700             OUT_BATCH( (b.y1 << 16) | b.x1 );
701             OUT_BATCH( (b.y2 << 16) | b.x2 );
702             OUT_BATCH( intelScreen->back.offset );
703             OUT_BATCH( clear_color );
704             ADVANCE_BATCH();
705          }
706
707          if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) {
708             BEGIN_BATCH( 6);
709             OUT_BATCH( D_CMD );
710             OUT_BATCH( BR13 );
711             OUT_BATCH( (b.y1 << 16) | b.x1 );
712             OUT_BATCH( (b.y2 << 16) | b.x2 );
713             OUT_BATCH( intelScreen->depth.offset );
714             OUT_BATCH( clear_depth );
715             ADVANCE_BATCH();
716          }      
717       }
718    }
719    intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
720    UNLOCK_HARDWARE( intel );
721 }
722
723
724
725
726 void intelDestroyBatchBuffer( GLcontext *ctx )
727 {
728    intelContextPtr intel = INTEL_CONTEXT(ctx);
729
730    if (intel->alloc.offset) {
731       intelFreeAGP( intel, intel->alloc.ptr );
732       intel->alloc.ptr = NULL;
733       intel->alloc.offset = 0;
734    }
735    else if (intel->alloc.ptr) {
736       free(intel->alloc.ptr);
737       intel->alloc.ptr = NULL;
738    }
739
740    memset(&intel->batch, 0, sizeof(intel->batch));
741 }
742
743
744 void intelInitBatchBuffer( GLcontext *ctx )
745 {
746    intelContextPtr intel = INTEL_CONTEXT(ctx);
747
748    /* This path isn't really safe with rotate:
749     */
750    if (getenv("INTEL_BATCH") && intel->intelScreen->allow_batchbuffer) {      
751       switch (intel->intelScreen->deviceID) {
752       case PCI_CHIP_I865_G:
753          /* HW bug?  Seems to crash if batchbuffer crosses 4k boundary.
754           */
755          intel->alloc.size = 8 * 1024; 
756          break;
757       default:
758          /* This is the smallest amount of memory the kernel deals with.
759           * We'd ideally like to make this smaller.
760           */
761          intel->alloc.size = 1 << intel->intelScreen->logTextureGranularity;
762          break;
763       }
764
765       intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size );
766       if (intel->alloc.ptr)
767          intel->alloc.offset = 
768             intelAgpOffsetFromVirtual( intel, intel->alloc.ptr );
769       else
770          intel->alloc.offset = 0; /* OK? */
771    }
772
773    /* The default is now to use a local buffer and pass that to the
774     * kernel.  This is also a fallback if allocation fails on the
775     * above path:
776     */
777    if (!intel->alloc.ptr) {
778       intel->alloc.size = 8 * 1024;
779       intel->alloc.ptr = malloc( intel->alloc.size );
780       intel->alloc.offset = 0;
781    }
782
783    assert(intel->alloc.ptr);
784 }