Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / savage / savageioctl.c
1 /*
2  * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3  * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sub license,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19  * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
25
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <sys/mman.h>
29
30 #include "main/mtypes.h"
31 #include "main/macros.h"
32 #include "main/dd.h"
33 #include "main/context.h"
34 #include "main/colormac.h"
35 #include "main/mm.h"
36 #include "swrast/swrast.h"
37
38 #include "savagecontext.h"
39 #include "savageioctl.h"
40 #include "savagestate.h"
41 #include "savagespan.h"
42
43 #include "drm.h"
44 #include <sys/timeb.h>
45
46 #define DEPTH_SCALE_16 ((1<<16)-1)
47 #define DEPTH_SCALE_24 ((1<<24)-1)
48
49
50 void savageGetDMABuffer( savageContextPtr imesa )
51 {
52    int idx = 0;
53    int size = 0;
54    drmDMAReq dma;
55    int retcode;
56    drmBufPtr buf;
57
58    assert (imesa->savageScreen->bufs);
59
60    if (SAVAGE_DEBUG & DEBUG_DMA)
61       fprintf(stderr,  "Getting dma buffer\n");
62
63    dma.context = imesa->hHWContext;
64    dma.send_count = 0;
65    dma.send_list = NULL;
66    dma.send_sizes = NULL;
67    dma.flags = 0;
68    dma.request_count = 1;
69    dma.request_size = imesa->bufferSize;
70    dma.request_list = &idx;
71    dma.request_sizes = &size;
72    dma.granted_count = 0;
73
74
75    if (SAVAGE_DEBUG & DEBUG_DMA)
76       fprintf(stderr, "drmDMA (get) ctx %d count %d size 0x%x\n",
77            dma.context, dma.request_count,
78            dma.request_size);
79
80    while (1) {
81       retcode = drmDMA(imesa->driFd, &dma);
82
83       if (SAVAGE_DEBUG & DEBUG_DMA)
84          fprintf(stderr, "retcode %d sz %d idx %d count %d\n",
85                  retcode,
86                  dma.request_sizes[0],
87                  dma.request_list[0],
88                  dma.granted_count);
89
90       if (retcode == 0 &&
91           dma.request_sizes[0] &&
92           dma.granted_count)
93          break;
94
95       if (SAVAGE_DEBUG & DEBUG_DMA)
96          fprintf(stderr, "\n\nflush");
97    }
98
99    buf = &(imesa->savageScreen->bufs->list[idx]);
100
101    if (SAVAGE_DEBUG & DEBUG_DMA)
102       fprintf(stderr,
103            "drmDMA (get) returns size[0] 0x%x idx[0] %d\n"
104            "dma_buffer now: buf idx: %d size: %d used: %d addr %p\n",
105            dma.request_sizes[0], dma.request_list[0],
106            buf->idx, buf->total,
107            buf->used, buf->address);
108
109    imesa->dmaVtxBuf.total = buf->total / 4;
110    imesa->dmaVtxBuf.used = 0;
111    imesa->dmaVtxBuf.flushed = 0;
112    imesa->dmaVtxBuf.idx = buf->idx;
113    imesa->dmaVtxBuf.buf = (uint32_t *)buf->address;
114
115    if (SAVAGE_DEBUG & DEBUG_DMA)
116       fprintf(stderr, "finished getbuffer\n");
117 }
118
119 #if 0
120 /* Still keeping this around because it demonstrates page flipping and
121  * automatic z-clear. */
122 static void savage_BCI_clear(struct gl_context *ctx, drm_savage_clear_t *pclear)
123 {
124         savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
125         int nbox = imesa->sarea->nbox;
126         drm_clip_rect_t *pbox = imesa->sarea->boxes;
127         int i;
128
129         
130         if (nbox > SAVAGE_NR_SAREA_CLIPRECTS)
131                 nbox = SAVAGE_NR_SAREA_CLIPRECTS;
132
133         for (i = 0 ; i < nbox ; i++, pbox++) {
134                 unsigned int x = pbox->x1;
135                 unsigned int y = pbox->y1;
136                 unsigned int width = pbox->x2 - x;
137                 unsigned int height = pbox->y2 - y;
138                 uint32_t *bciptr;
139
140                 if (pbox->x1 > pbox->x2 ||
141                     pbox->y1 > pbox->y2 ||
142                     pbox->x2 > imesa->savageScreen->width ||
143                     pbox->y2 > imesa->savageScreen->height)
144                         continue;
145
146                 if ( pclear->flags & SAVAGE_FRONT ) {
147                         bciptr = savageDMAAlloc (imesa, 8);
148                         WRITE_CMD((bciptr) , 0x4BCC8C00,uint32_t);
149                         WRITE_CMD((bciptr) , imesa->savageScreen->frontOffset,uint32_t);
150                         WRITE_CMD((bciptr) , imesa->savageScreen->frontBitmapDesc,uint32_t);
151                         WRITE_CMD((bciptr) , pclear->clear_color,uint32_t);
152                         WRITE_CMD((bciptr) , (y <<16) | x,uint32_t);
153                         WRITE_CMD((bciptr) , (height << 16) | width,uint32_t);
154                         savageDMACommit (imesa, bciptr);
155                 }
156                 if ( pclear->flags & SAVAGE_BACK ) {
157                         bciptr = savageDMAAlloc (imesa, 8);
158                         WRITE_CMD((bciptr) , 0x4BCC8C00,uint32_t);
159                         WRITE_CMD((bciptr) , imesa->savageScreen->backOffset,uint32_t);
160                         WRITE_CMD((bciptr) , imesa->savageScreen->backBitmapDesc,uint32_t);
161                         WRITE_CMD((bciptr) , pclear->clear_color,uint32_t);
162                         WRITE_CMD((bciptr) , (y <<16) | x,uint32_t);
163                         WRITE_CMD((bciptr) , (height << 16) | width,uint32_t);
164                         savageDMACommit (imesa, bciptr);
165                 }
166                 
167                 if ( pclear->flags & (SAVAGE_DEPTH |SAVAGE_STENCIL) ) {
168                         uint32_t writeMask = 0x0;
169                         if(imesa->hw_stencil)
170                         {        
171                             if(pclear->flags & SAVAGE_STENCIL)
172                             {
173                           
174                                  writeMask |= 0xFF000000;
175                             }
176                             if(pclear->flags & SAVAGE_DEPTH)
177                             {
178                                  writeMask |= 0x00FFFFFF;
179                             }
180                         }
181                         if(imesa->IsFullScreen && imesa->NotFirstFrame &&
182                            imesa->savageScreen->chipset >= S3_SAVAGE4)
183                         {
184                             imesa->regs.s4.zBufCtrl.ni.autoZEnable = GL_TRUE;
185                             imesa->regs.s4.zBufCtrl.ni.frameID =
186                                 ~imesa->regs.s4.zBufCtrl.ni.frameID;
187                             
188                             imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
189                         }
190                         else
191                         {
192                             if(imesa->IsFullScreen)
193                                 imesa->NotFirstFrame = GL_TRUE;
194                                 
195                             if(imesa->hw_stencil)
196                             {
197                                 bciptr = savageDMAAlloc (imesa, 10);
198                                 if(writeMask != 0xFFFFFFFF)
199                                 {
200                                     WRITE_CMD((bciptr) , 0x960100D7,uint32_t);
201                                     WRITE_CMD((bciptr) , writeMask,uint32_t);
202                                 }
203                             }
204                             else
205                             {
206                                 bciptr = savageDMAAlloc (imesa, 6);
207                             }
208
209                             WRITE_CMD((bciptr) , 0x4BCC8C00,uint32_t);
210                             WRITE_CMD((bciptr) , imesa->savageScreen->depthOffset,uint32_t);
211                             WRITE_CMD((bciptr) , imesa->savageScreen->depthBitmapDesc,uint32_t);
212                             WRITE_CMD((bciptr) , pclear->clear_depth,uint32_t);
213                             WRITE_CMD((bciptr) , (y <<16) | x,uint32_t);
214                             WRITE_CMD((bciptr) , (height << 16) | width,uint32_t);
215                             if(imesa->hw_stencil)
216                             {
217                                 if(writeMask != 0xFFFFFFFF)
218                                 {
219                                    WRITE_CMD((bciptr) , 0x960100D7,uint32_t);
220                                    WRITE_CMD((bciptr) , 0xFFFFFFFF,uint32_t);  
221                                 }
222                             }
223                             savageDMACommit (imesa, bciptr);
224                         }
225                 }
226         }
227         /* FK: Make sure that the clear stuff is emitted. Otherwise a
228            software fallback may get overwritten by a delayed clear. */
229         savageDMAFlush (imesa);
230 }
231
232 static void savage_BCI_swap(savageContextPtr imesa)
233 {
234     int nbox = imesa->sarea->nbox;
235     drm_clip_rect_t *pbox = imesa->sarea->boxes;
236     int i;
237     volatile uint32_t *bciptr;
238     
239     if (nbox > SAVAGE_NR_SAREA_CLIPRECTS)
240         nbox = SAVAGE_NR_SAREA_CLIPRECTS;
241     savageDMAFlush (imesa);
242     
243     if(imesa->IsFullScreen)
244     { /* full screen*/
245         unsigned int tmp0;
246         tmp0 = imesa->savageScreen->frontOffset; 
247         imesa->savageScreen->frontOffset = imesa->savageScreen->backOffset;
248         imesa->savageScreen->backOffset = tmp0;
249         
250         if(imesa->toggle == TARGET_BACK)
251             imesa->toggle = TARGET_FRONT;
252         else
253             imesa->toggle = TARGET_BACK; 
254         
255         driFlipRenderbuffers(imesa->glCtx->DrawBuffer,
256                              imesa->toggle != TARGET_FRONT);
257
258         imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
259         imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
260         bciptr = SAVAGE_GET_BCI_POINTER(imesa,3);
261         *(bciptr) = 0x960100B0;
262         *(bciptr) = (imesa->savageScreen->frontOffset); 
263         *(bciptr) = 0xA0000000;
264     } 
265     
266     else
267     {  /* Use bitblt copy from back to front buffer*/
268         
269         for (i = 0 ; i < nbox; i++, pbox++)
270         {
271             unsigned int w = pbox->x2 - pbox->x1;
272             unsigned int h = pbox->y2 - pbox->y1;
273             
274             if (pbox->x1 > pbox->x2 ||
275                 pbox->y1 > pbox->y2 ||
276                 pbox->x2 > imesa->savageScreen->width ||
277                 pbox->y2 > imesa->savageScreen->height)
278                 continue;
279
280             bciptr = SAVAGE_GET_BCI_POINTER(imesa,6);
281             
282             *(bciptr) = 0x4BCC00C0;
283             
284             *(bciptr) = imesa->savageScreen->backOffset;
285             *(bciptr) = imesa->savageScreen->backBitmapDesc;
286             *(bciptr) = (pbox->y1 <<16) | pbox->x1;   /*x0, y0*/
287             *(bciptr) = (pbox->y1 <<16) | pbox->x1;
288             *(bciptr) = (h << 16) | w;
289         }
290         
291     }
292 }
293 #endif
294
295
296 static GLboolean intersect_rect( drm_clip_rect_t *out,
297                                  const drm_clip_rect_t *a,
298                                  const drm_clip_rect_t *b )
299 {
300    *out = *a;
301    if (b->x1 > out->x1) out->x1 = b->x1;
302    if (b->y1 > out->y1) out->y1 = b->y1;
303    if (b->x2 < out->x2) out->x2 = b->x2;
304    if (b->y2 < out->y2) out->y2 = b->y2;
305
306    return ((out->x1 < out->x2) && (out->y1 < out->y2));
307 }
308
309
310 static GLuint savageIntersectClipRects(drm_clip_rect_t *dest,
311                                        const drm_clip_rect_t *src,
312                                        GLuint nsrc,
313                                        const drm_clip_rect_t *clip)
314 {
315     GLuint i, ndest;
316
317     for (i = 0, ndest = 0; i < nsrc; ++i, ++src) {
318         if (intersect_rect(dest, src, clip)) {
319             dest++;
320             ndest++;
321         }
322     }
323
324     return ndest;
325 }
326
327
328 static void savageDDClear( struct gl_context *ctx, GLbitfield mask )
329 {
330    savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
331    GLuint colorMask, depthMask, clearColor, clearDepth, flags;
332    GLint cx = ctx->DrawBuffer->_Xmin;
333    GLint cy = ctx->DrawBuffer->_Ymin;
334    GLint cw = ctx->DrawBuffer->_Xmax - cx;
335    GLint ch = ctx->DrawBuffer->_Ymax - cy;
336
337    /* XXX FIX ME: the cx,cy,cw,ch vars are currently ignored! */
338    (void) ch;
339    (void) cw;
340
341    if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
342        fprintf (stderr, "%s\n", __FUNCTION__);
343
344    clearColor = imesa->ClearColor;
345    if (imesa->float_depth) {
346        if (imesa->savageScreen->zpp == 2)
347            clearDepth = savageEncodeFloat16(1.0 - ctx->Depth.Clear);
348        else
349            clearDepth = savageEncodeFloat24(1.0 - ctx->Depth.Clear);
350    } else {
351        if (imesa->savageScreen->zpp == 2)
352            clearDepth = (GLuint) ((1.0 - ctx->Depth.Clear) * DEPTH_SCALE_16);
353        else
354            clearDepth = (GLuint) ((1.0 - ctx->Depth.Clear) * DEPTH_SCALE_24);
355    }
356
357    colorMask = 0;
358    depthMask = 0;
359    switch (imesa->savageScreen->cpp) {
360    case 2:
361        colorMask = PACK_COLOR_565(ctx->Color.ColorMask[0][0],
362                                   ctx->Color.ColorMask[0][1],
363                                   ctx->Color.ColorMask[0][2]);
364        break;
365    case 4:
366        colorMask = PACK_COLOR_8888(ctx->Color.ColorMask[0][3],
367                                    ctx->Color.ColorMask[0][2],
368                                    ctx->Color.ColorMask[0][1],
369                                    ctx->Color.ColorMask[0][0]);
370        break;
371    }
372
373    flags = 0;
374
375    if (mask & BUFFER_BIT_FRONT_LEFT) {
376       flags |= SAVAGE_FRONT;
377       mask &= ~BUFFER_BIT_FRONT_LEFT;
378    }
379
380    if (mask & BUFFER_BIT_BACK_LEFT) {
381       flags |= SAVAGE_BACK;
382       mask &= ~BUFFER_BIT_BACK_LEFT;
383    }
384
385    if ((mask & BUFFER_BIT_DEPTH) && ctx->Depth.Mask) {
386       flags |= SAVAGE_DEPTH;
387       depthMask |=
388           (imesa->savageScreen->zpp == 2) ? 0xffffffff : 0x00ffffff;
389       mask &= ~BUFFER_BIT_DEPTH;
390    }
391    
392    if((mask & BUFFER_BIT_STENCIL) && imesa->hw_stencil)
393    {
394       flags |= SAVAGE_DEPTH;
395       depthMask |= 0xff000000;
396       mask &= ~BUFFER_BIT_STENCIL;
397    }
398
399    savageFlushVertices(imesa);
400
401    if (flags) {
402        GLboolean depthCleared = GL_FALSE;
403        if (flags & (SAVAGE_FRONT|SAVAGE_BACK)) {
404            drm_savage_cmd_header_t *cmd;
405            cmd = savageAllocCmdBuf(imesa, sizeof(drm_savage_cmd_header_t));
406            cmd[0].clear0.cmd = SAVAGE_CMD_CLEAR;
407            if ((flags & SAVAGE_DEPTH) &&
408                clearDepth == clearColor && depthMask == colorMask) {
409                cmd[0].clear0.flags = flags;
410                depthCleared = GL_TRUE;
411            } else
412                cmd[0].clear0.flags = flags & (SAVAGE_FRONT|SAVAGE_BACK);
413            cmd[1].clear1.mask = colorMask;
414            cmd[1].clear1.value = clearColor;
415        }
416
417        if ((flags & SAVAGE_DEPTH) && !depthCleared) {
418            drm_savage_cmd_header_t *cmd;
419            cmd = savageAllocCmdBuf(imesa, sizeof(drm_savage_cmd_header_t));
420            cmd[0].clear0.cmd = SAVAGE_CMD_CLEAR;
421            cmd[0].clear0.flags = SAVAGE_DEPTH;
422            cmd[1].clear1.mask = depthMask;
423            cmd[1].clear1.value = clearDepth;
424        }
425    }
426
427    if (mask) 
428       _swrast_Clear( ctx, mask );
429 }
430
431 /*
432  * Copy the back buffer to the front buffer. 
433  */
434 void savageSwapBuffers( __DRIdrawable *dPriv )
435 {
436    savageContextPtr imesa;
437
438    if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
439        fprintf (stderr, "%s\n================================\n", __FUNCTION__);
440
441    assert(dPriv);
442    assert(dPriv->driContextPriv);
443    assert(dPriv->driContextPriv->driverPrivate);
444
445    imesa = (savageContextPtr) dPriv->driContextPriv->driverPrivate;
446    if (imesa->IsDouble)
447        _mesa_notifySwapBuffers( imesa->glCtx );
448
449    FLUSH_BATCH(imesa);
450
451    if (imesa->sync_frames)
452        imesa->lastSwap = savageEmitEvent( imesa, 0 );
453
454    if (imesa->lastSwap != 0)
455        savageWaitEvent( imesa, imesa->lastSwap );
456
457    {
458        drm_savage_cmd_header_t *cmd = savageAllocCmdBuf(imesa, 0);
459        cmd->cmd.cmd = SAVAGE_CMD_SWAP;
460        imesa->inSwap = GL_TRUE; /* ignore scissors in savageFlushCmdBuf */
461        savageFlushCmdBuf(imesa, GL_FALSE);
462        imesa->inSwap = GL_FALSE;
463    }
464
465    if (!imesa->sync_frames)
466        /* don't sync, but limit the lag to one frame. */
467        imesa->lastSwap = savageEmitEvent( imesa, 0 );
468 }
469
470 unsigned int savageEmitEventLocked( savageContextPtr imesa, unsigned int flags )
471 {
472     drm_savage_event_emit_t event;
473     int ret;
474     event.count = 0;
475     event.flags = flags;
476     ret = drmCommandWriteRead( imesa->driFd, DRM_SAVAGE_BCI_EVENT_EMIT,
477                                &event, sizeof(event) );
478     if (ret) {
479         fprintf (stderr, "emit event returned %d\n", ret);
480         exit (1);
481     }
482     return event.count;
483 }
484 unsigned int savageEmitEvent( savageContextPtr imesa, unsigned int flags )
485 {
486     unsigned int ret;
487     LOCK_HARDWARE( imesa );
488     ret = savageEmitEventLocked( imesa, flags );
489     UNLOCK_HARDWARE( imesa );
490     return ret;
491 }
492
493
494 void savageWaitEvent( savageContextPtr imesa, unsigned int count )
495 {
496     drm_savage_event_wait_t event;
497     int ret;
498     event.count = count;
499     event.flags = 0;
500     ret = drmCommandWriteRead( imesa->driFd, DRM_SAVAGE_BCI_EVENT_WAIT,
501                                &event, sizeof(event) );
502     if (ret) {
503         fprintf (stderr, "wait event returned %d\n", ret);
504         exit (1);
505     }
506 }
507
508
509 void savageFlushVertices( savageContextPtr imesa )
510 {
511     struct savage_vtxbuf_t *buffer = imesa->vtxBuf;
512
513     if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
514         fprintf (stderr, "%s\n", __FUNCTION__);
515
516     if (!buffer->total)
517         return;
518
519     if (buffer->used > buffer->flushed) {
520         drm_savage_cmd_header_t *cmd;
521         /* State must be updated "per primitive" because hardware
522          * culling must be disabled for unfilled primitives, points
523          * and lines. */
524         savageEmitChangedState (imesa);
525         cmd = savageAllocCmdBuf(imesa, 0);
526         cmd->prim.cmd = buffer == &imesa->dmaVtxBuf ?
527             SAVAGE_CMD_DMA_PRIM : SAVAGE_CMD_VB_PRIM;
528         cmd->prim.prim = imesa->HwPrim;
529         cmd->prim.skip = imesa->skip;
530         cmd->prim.start = buffer->flushed / imesa->HwVertexSize;
531         cmd->prim.count = buffer->used / imesa->HwVertexSize - cmd->prim.start;
532         buffer->flushed = buffer->used;
533     }
534 }
535
536 void savageFlushCmdBufLocked( savageContextPtr imesa, GLboolean discard )
537 {
538     __DRIdrawable *dPriv = imesa->driDrawable;
539
540     if (!imesa->dmaVtxBuf.total)
541         discard = GL_FALSE;
542
543     /* complete indexed drawing commands */
544     savageFlushElts(imesa);
545
546     if (imesa->cmdBuf.write != imesa->cmdBuf.start || discard) {
547         drm_savage_cmdbuf_t cmdbuf;
548         drm_savage_cmd_header_t *start;
549         int ret;
550
551         /* If we lost the context we must restore the initial state (at
552          * the start of the command buffer). */
553         if (imesa->lostContext) {
554             start = imesa->cmdBuf.base;
555             imesa->lostContext = GL_FALSE;
556         } else
557             start = imesa->cmdBuf.start;
558
559         if ((SAVAGE_DEBUG & DEBUG_DMA) && discard)
560             fprintf (stderr, "Discarding DMA buffer, used=%u\n",
561                      imesa->dmaVtxBuf.used);
562
563         cmdbuf.dma_idx = imesa->dmaVtxBuf.idx;
564         cmdbuf.discard = discard;
565         cmdbuf.vb_addr = imesa->clientVtxBuf.buf;
566         cmdbuf.vb_size = imesa->clientVtxBuf.total*4;
567         cmdbuf.vb_stride = imesa->HwVertexSize;
568         cmdbuf.cmd_addr = start;
569         cmdbuf.size = (imesa->cmdBuf.write - start);
570         if (!imesa->inSwap && imesa->scissor.enabled) {
571             drm_clip_rect_t *box = dPriv->pClipRects, *ibox;
572             drm_clip_rect_t scissor;
573             GLuint nbox = dPriv->numClipRects, nibox;
574             /* transform and clip scissor to viewport */
575             scissor.x1 = MAX2(imesa->scissor.x, 0) + dPriv->x;
576             scissor.y1 = MAX2(dPriv->h - imesa->scissor.y - imesa->scissor.h,
577                               0) + dPriv->y;
578             scissor.x2 = MIN2(imesa->scissor.x + imesa->scissor.w,
579                               dPriv->w) + dPriv->x;
580             scissor.y2 = MIN2(dPriv->h - imesa->scissor.y,
581                               dPriv->h) + dPriv->y;
582             /* intersect cliprects with scissor */
583             ibox = malloc(dPriv->numClipRects*sizeof(drm_clip_rect_t));
584             if (!ibox) {
585                 fprintf(stderr, "Out of memory.\n");
586                 exit(1);
587             }
588             nibox = savageIntersectClipRects(ibox, box, nbox, &scissor);
589             cmdbuf.nbox = nibox;
590             cmdbuf.box_addr = ibox;
591         } else {
592             cmdbuf.nbox = dPriv->numClipRects;
593             cmdbuf.box_addr = dPriv->pClipRects;
594         }
595
596         ret = drmCommandWrite( imesa->driFd, DRM_SAVAGE_BCI_CMDBUF,
597                                &cmdbuf, sizeof(cmdbuf) );
598         if (ret) {
599             fprintf (stderr, "cmdbuf ioctl returned %d\n", ret);
600             exit(1);
601         }
602
603         if (cmdbuf.box_addr != dPriv->pClipRects) {
604             free(cmdbuf.box_addr);
605         }
606
607         /* Save the current state at the start of the command buffer. That
608          * state will only be emitted, if the context was lost since the
609          * last command buffer. */
610         imesa->cmdBuf.write = imesa->cmdBuf.base;
611         savageEmitOldState(imesa);
612         imesa->cmdBuf.start = imesa->cmdBuf.write;
613     }
614
615     if (discard) {
616         assert (!savageHaveIndexedVerts(imesa));
617         imesa->dmaVtxBuf.total = 0;
618         imesa->dmaVtxBuf.used = 0;
619         imesa->dmaVtxBuf.flushed = 0;
620     }
621     if (!savageHaveIndexedVerts(imesa)) {
622         imesa->clientVtxBuf.used = 0;
623         imesa->clientVtxBuf.flushed = 0;
624     }
625 }
626
627
628 void savageFlushCmdBuf( savageContextPtr imesa, GLboolean discard ) 
629 {
630     if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
631         fprintf (stderr, "%s\n", __FUNCTION__);
632     LOCK_HARDWARE(imesa);
633     savageFlushCmdBufLocked (imesa, discard);
634     UNLOCK_HARDWARE(imesa);
635 }
636
637
638 static void savageDDFlush( struct gl_context *ctx )
639 {
640     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
641     if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
642         fprintf (stderr, "%s\n", __FUNCTION__);
643     savageFlushVertices (imesa);
644     savageFlushCmdBuf(imesa, GL_FALSE);
645 }
646
647 static void savageDDFinish( struct gl_context *ctx  ) 
648 {
649     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
650     if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
651         fprintf (stderr, "%s\n", __FUNCTION__);
652     savageFlushVertices (imesa);
653     savageFlushCmdBuf(imesa, GL_FALSE);
654     WAIT_IDLE_EMPTY(imesa);
655 }
656
657 void savageDDInitIoctlFuncs( struct gl_context *ctx )
658 {
659    ctx->Driver.Clear = savageDDClear;
660    ctx->Driver.Flush = savageDDFlush;
661    ctx->Driver.Finish = savageDDFinish;
662 }