efb7cf6b6cf21a049ff5b8835dc8c577fc7bab50
[mesa.git] / src / mesa / drivers / dri / unichrome / via_ioctl.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 #include <stdio.h>
25 #include <unistd.h>
26
27 #include "glheader.h"
28 #include "mtypes.h"
29 #include "macros.h"
30 #include "dd.h"
31 #include "swrast/swrast.h"
32
33 #include "mm.h"
34 #include "via_context.h"
35 #include "via_tris.h"
36 #include "via_ioctl.h"
37 #include "via_state.h"
38
39 #include "vblank.h"
40 #include "drm.h"
41 #include "xf86drm.h"
42 #include <sys/ioctl.h>
43 #include <errno.h>
44
45
46 #define VIA_REG_STATUS 0x400
47 #define VIA_REG_GEMODE 0x004
48 #define VIA_REG_SRCBASE 0x030
49 #define VIA_REG_DSTBASE 0x034
50 #define VIA_REG_PITCH 0x038
51 #define VIA_REG_SRCCOLORKEY 0x01C
52 #define VIA_REG_KEYCONTROL 0x02C
53 #define VIA_REG_SRCPOS 0x008
54 #define VIA_REG_DSTPOS 0x00C
55 #define VIA_REG_GECMD 0x000
56 #define VIA_REG_DIMENSION 0x010 /* width and height */
57 #define VIA_REG_FGCOLOR 0x018
58
59 #define VIA_GEM_8bpp 0x00000000
60 #define VIA_GEM_16bpp 0x00000100
61 #define VIA_GEM_32bpp 0x00000300
62 #define VIA_GEC_BLT 0x00000001
63 #define VIA_PITCH_ENABLE 0x80000000
64 #define VIA_GEC_INCX 0x00000000
65 #define VIA_GEC_DECY 0x00004000
66 #define VIA_GEC_INCY 0x00000000
67 #define VIA_GEC_DECX 0x00008000
68 #define VIA_GEC_FIXCOLOR_PAT 0x00002000
69
70
71 #define VIA_BLIT_CLEAR 0x00
72 #define VIA_BLIT_COPY 0xCC
73 #define VIA_BLIT_FILL 0xF0
74 #define VIA_BLIT_SET 0xFF
75
76 static void dump_dma( viaContextPtr vmesa )
77 {
78 GLuint i;
79 GLuint *data = (GLuint *)vmesa->dma;
80 for (i = 0; i < vmesa->dmaLow; i += 16) {
81 fprintf(stderr, "%04x: ", i);
82 fprintf(stderr, "%08x ", *data++);
83 fprintf(stderr, "%08x ", *data++);
84 fprintf(stderr, "%08x ", *data++);
85 fprintf(stderr, "%08x\n", *data++);
86 }
87 fprintf(stderr, "******************************************\n");
88 }
89
90
91
92 void viaCheckDma(viaContextPtr vmesa, GLuint bytes)
93 {
94 VIA_FINISH_PRIM( vmesa );
95 if (vmesa->dmaLow + bytes > VIA_DMA_HIGHWATER) {
96 viaFlushDma(vmesa);
97 }
98 }
99
100
101
102 #define SetReg2DAGP(nReg, nData) do { \
103 OUT_RING( ((nReg) >> 2) | 0xF0000000 ); \
104 OUT_RING( nData ); \
105 } while (0)
106
107
108 static void viaBlit(viaContextPtr vmesa, GLuint bpp,
109 GLuint srcBase, GLuint srcPitch,
110 GLuint dstBase, GLuint dstPitch,
111 GLuint w, GLuint h,
112 GLuint blitMode,
113 GLuint color, GLuint nMask )
114 {
115
116 GLuint dwGEMode, srcX, dstX, cmd;
117 RING_VARS;
118
119 if (VIA_DEBUG)
120 fprintf(stderr, "%s bpp %d src %x/%x dst %x/%x w %d h %d mode: %x color: 0x%08x mask 0x%08x\n",
121 __FUNCTION__, bpp, srcBase, srcPitch, dstBase, dstPitch, w,h, blitMode, color, nMask);
122
123
124 if (!w || !h)
125 return;
126
127 switch (bpp) {
128 case 16:
129 dwGEMode = VIA_GEM_16bpp;
130 srcX = (srcBase & 0x1f) >> 1;
131 dstX = (dstBase & 0x1f) >> 1;
132 break;
133 case 32:
134 dwGEMode = VIA_GEM_32bpp;
135 srcX = (srcBase & 0x1f) >> 2;
136 dstX = (dstBase & 0x1f) >> 2;
137 break;
138 default:
139 return;
140 }
141
142 switch(blitMode) {
143 case VIA_BLIT_FILL:
144 cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | (VIA_BLIT_FILL << 24);
145 break;
146 case VIA_BLIT_COPY:
147 cmd = VIA_GEC_BLT | (VIA_BLIT_COPY << 24);
148 break;
149 default:
150 return;
151 }
152
153 BEGIN_RING(22);
154 SetReg2DAGP( VIA_REG_GEMODE, dwGEMode);
155 SetReg2DAGP( VIA_REG_FGCOLOR, color);
156 SetReg2DAGP( 0x2C, nMask);
157 SetReg2DAGP( VIA_REG_SRCBASE, (srcBase & ~0x1f) >> 3);
158 SetReg2DAGP( VIA_REG_DSTBASE, (dstBase & ~0x1f) >> 3);
159 SetReg2DAGP( VIA_REG_PITCH, VIA_PITCH_ENABLE |
160 (srcPitch >> 3) | ((dstPitch >> 3) << 16));
161 SetReg2DAGP( VIA_REG_SRCPOS, srcX);
162 SetReg2DAGP( VIA_REG_DSTPOS, dstX);
163 SetReg2DAGP( VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1)));
164 SetReg2DAGP( VIA_REG_GECMD, cmd);
165 SetReg2DAGP( 0x2C, 0x00000000);
166 ADVANCE_RING();
167 }
168
169 static void viaFillBuffer(viaContextPtr vmesa,
170 viaBuffer *buffer,
171 drm_clip_rect_t *pbox,
172 int nboxes,
173 GLuint pixel,
174 GLuint mask)
175 {
176 GLuint bytePerPixel = buffer->bpp >> 3;
177 GLuint i;
178
179 for (i = 0; i < nboxes ; i++) {
180 int x = pbox[i].x1 - vmesa->drawX;
181 int y = pbox[i].y1 - vmesa->drawY;
182 int w = pbox[i].x2 - pbox[i].x1;
183 int h = pbox[i].y2 - pbox[i].y1;
184
185 int offset = (buffer->orig +
186 y * buffer->pitch +
187 x * bytePerPixel);
188
189 viaBlit(vmesa,
190 buffer->bpp,
191 offset, buffer->pitch,
192 offset, buffer->pitch,
193 w, h,
194 VIA_BLIT_FILL, pixel, mask);
195 }
196 }
197
198
199
200 static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
201 GLint cx, GLint cy, GLint cw, GLint ch)
202 {
203 viaContextPtr vmesa = VIA_CONTEXT(ctx);
204 __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
205 int flag = 0;
206 GLuint i = 0;
207 GLuint clear_depth_mask = 0xf << 28;
208 GLuint clear_depth = 0;
209
210 VIA_FLUSH_DMA(vmesa);
211
212 if (mask & DD_FRONT_LEFT_BIT) {
213 flag |= VIA_FRONT;
214 mask &= ~DD_FRONT_LEFT_BIT;
215 }
216
217 if (mask & DD_BACK_LEFT_BIT) {
218 flag |= VIA_BACK;
219 mask &= ~DD_BACK_LEFT_BIT;
220 }
221
222 if (mask & DD_DEPTH_BIT) {
223 flag |= VIA_DEPTH;
224 clear_depth = (GLuint)(ctx->Depth.Clear * vmesa->ClearDepth);
225 clear_depth_mask &= ~vmesa->depth_clear_mask;
226 mask &= ~DD_DEPTH_BIT;
227 }
228
229 if (mask & DD_STENCIL_BIT) {
230 if (vmesa->have_hw_stencil) {
231 if (ctx->Stencil.WriteMask[0] == 0xff) {
232 flag |= VIA_DEPTH;
233 clear_depth &= ~0xff;
234 clear_depth |= (ctx->Stencil.Clear & 0xff);
235 clear_depth_mask &= ~vmesa->stencil_clear_mask;
236 mask &= ~DD_STENCIL_BIT;
237 }
238 else {
239 if (VIA_DEBUG)
240 fprintf(stderr, "XXX: Clear stencil writemask %x -- need triangles (or a ROP?)\n",
241 ctx->Stencil.WriteMask[0]);
242 }
243 }
244 }
245
246 if (flag) {
247 drm_clip_rect_t *boxes, *tmp_boxes = 0;
248 int nr = 0;
249
250 LOCK_HARDWARE(vmesa);
251
252 /* flip top to bottom */
253 cy = dPriv->h - cy - ch;
254 cx += vmesa->drawX + vmesa->drawXoff;
255 cy += vmesa->drawY;
256
257 if (!all) {
258 drm_clip_rect_t *b = vmesa->pClipRects;
259
260 boxes = tmp_boxes = (drm_clip_rect_t *)malloc(vmesa->numClipRects *
261 sizeof(drm_clip_rect_t));
262 if (!boxes) {
263 UNLOCK_HARDWARE(vmesa);
264 return;
265 }
266
267 for (; i < vmesa->numClipRects; i++) {
268 GLint x = b[i].x1;
269 GLint y = b[i].y1;
270 GLint w = b[i].x2 - x;
271 GLint h = b[i].y2 - y;
272
273 if (x < cx) w -= cx - x, x = cx;
274 if (y < cy) h -= cy - y, y = cy;
275 if (x + w > cx + cw) w = cx + cw - x;
276 if (y + h > cy + ch) h = cy + ch - y;
277 if (w <= 0) continue;
278 if (h <= 0) continue;
279
280 boxes[nr].x1 = x;
281 boxes[nr].y1 = y;
282 boxes[nr].x2 = x + w;
283 boxes[nr].y2 = y + h;
284 nr++;
285 }
286 }
287 else {
288 boxes = vmesa->pClipRects;
289 nr = vmesa->numClipRects;
290 }
291
292 if (flag & VIA_FRONT) {
293 viaFillBuffer(vmesa, &vmesa->front, boxes, nr, vmesa->ClearColor, vmesa->ClearMask);
294 }
295
296 if (flag & VIA_BACK) {
297 viaFillBuffer(vmesa, &vmesa->back, boxes, nr, vmesa->ClearColor, vmesa->ClearMask);
298 }
299
300 if (flag & VIA_DEPTH) {
301 viaFillBuffer(vmesa, &vmesa->depth, boxes, nr, clear_depth, clear_depth_mask);
302 }
303
304 viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS);
305 UNLOCK_HARDWARE(vmesa);
306
307 if (tmp_boxes)
308 free(tmp_boxes);
309 }
310
311 if (mask)
312 _swrast_Clear(ctx, mask, all, cx, cy, cw, ch);
313 }
314
315
316
317
318 static void viaDoSwapBuffers(viaContextPtr vmesa,
319 drm_clip_rect_t *b,
320 GLuint nbox)
321 {
322 GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
323 viaBuffer *front = &vmesa->front;
324 viaBuffer *back = &vmesa->back;
325 GLuint i;
326
327 for (i = 0; i < nbox; i++, b++) {
328 GLint x = b->x1 - vmesa->drawX;
329 GLint y = b->y1 - vmesa->drawY;
330 GLint w = b->x2 - b->x1;
331 GLint h = b->y2 - b->y1;
332
333 GLuint src = back->orig + y * back->pitch + x * bytePerPixel;
334 GLuint dest = front->orig + y * front->pitch + x * bytePerPixel;
335
336 viaBlit(vmesa,
337 bytePerPixel << 3,
338 src, back->pitch,
339 dest, front->pitch,
340 w, h,
341 VIA_BLIT_COPY, 0, 0);
342 }
343 }
344
345
346
347
348 /*
349 * Copy the back buffer to the front buffer.
350 */
351 void viaCopyBuffer(const __DRIdrawablePrivate *dPriv)
352 {
353 viaContextPtr vmesa = (viaContextPtr)dPriv->driContextPriv->driverPrivate;
354 GLboolean missed_target;
355
356 VIA_FLUSH_DMA(vmesa);
357 driWaitForVBlank( dPriv, & vmesa->vbl_seq, vmesa->vblank_flags, & missed_target );
358 if ( missed_target ) {
359 vmesa->swap_missed_count++;
360 vmesa->get_ust( &vmesa->swap_missed_ust );
361 }
362 LOCK_HARDWARE(vmesa);
363
364 viaDoSwapBuffers(vmesa, dPriv->pClipRects, dPriv->numClipRects);
365 viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS);
366
367 UNLOCK_HARDWARE(vmesa);
368 vmesa->swap_count++;
369 vmesa->get_ust( &vmesa->swap_ust );
370 }
371
372 /*
373 * XXX implement when full-screen extension is done.
374 */
375 void viaPageFlip(const __DRIdrawablePrivate *dPriv)
376 {
377 viaContextPtr vmesa = (viaContextPtr)dPriv->driContextPriv->driverPrivate;
378 viaBuffer buffer_tmp;
379 GLboolean missed_target;
380
381
382 VIA_FLUSH_DMA(vmesa);
383 driWaitForVBlank( dPriv, &vmesa->vbl_seq, vmesa->vblank_flags, &missed_target );
384 if ( missed_target ) {
385 vmesa->swap_missed_count++;
386 vmesa->get_ust( &vmesa->swap_missed_ust );
387 }
388 LOCK_HARDWARE(vmesa);
389
390 {
391 RING_VARS;
392
393 if (!vmesa->nDoneFirstFlip) {
394 vmesa->nDoneFirstFlip = GL_FALSE; /* XXX: FIXME LATER!!! */
395 BEGIN_RING(4);
396 OUT_RING(HALCYON_HEADER2);
397 OUT_RING(0x00fe0000);
398 OUT_RING(0x0000000e);
399 OUT_RING(0x0000000e);
400 ADVANCE_RING();
401 }
402
403 BEGIN_RING(4);
404 OUT_RING( HALCYON_HEADER2 );
405 OUT_RING( 0x00fe0000 );
406 OUT_RING((HC_SubA_HFBBasL << 24) | (vmesa->back.offset & 0xFFFFF8) | 0x2);
407 OUT_RING((HC_SubA_HFBDrawFirst << 24) |
408 ((vmesa->back.offset & 0xFF000000) >> 24) | 0x0100);
409 ADVANCE_RING();
410
411 }
412
413 viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS);
414 UNLOCK_HARDWARE(vmesa);
415 vmesa->swap_count++;
416 vmesa->get_ust( &vmesa->swap_ust );
417
418 /* KW: FIXME: When buffers are freed, could free frontbuffer by
419 * accident:
420 */
421 memcpy(&buffer_tmp, &vmesa->back, sizeof(viaBuffer));
422 memcpy(&vmesa->back, &vmesa->front, sizeof(viaBuffer));
423 memcpy(&vmesa->front, &buffer_tmp, sizeof(viaBuffer));
424
425 if(vmesa->currentPage) {
426 vmesa->currentPage = 0;
427 }
428 else {
429 vmesa->currentPage = 1;
430 }
431
432 if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__);
433 }
434
435
436
437
438 #define VIA_CMDBUF_MAX_LAG 50000
439
440 static int fire_buffer(viaContextPtr vmesa)
441 {
442 drm_via_cmdbuffer_t bufI;
443 int ret;
444
445 bufI.buf = (char *)vmesa->dma;
446 bufI.size = vmesa->dmaLow;
447
448 if (vmesa->useAgp) {
449 drm_via_cmdbuf_size_t bSiz;
450
451 /* Do the CMDBUF_SIZE ioctl:
452 */
453 bSiz.func = VIA_CMDBUF_LAG;
454 bSiz.wait = 1;
455 bSiz.size = VIA_CMDBUF_MAX_LAG;
456 do {
457 ret = drmCommandWriteRead(vmesa->driFd, DRM_VIA_CMDBUF_SIZE,
458 &bSiz, sizeof(bSiz));
459 } while (ret == -EAGAIN);
460 if (ret) {
461 UNLOCK_HARDWARE(vmesa);
462 fprintf(stderr, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n", __FUNCTION__, ret);
463 abort();
464 return ret;
465 }
466
467 /* Actually fire the buffer:
468 */
469 do {
470 ret = drmCommandWrite(vmesa->driFd, DRM_VIA_CMDBUFFER,
471 &bufI, sizeof(bufI));
472 } while (ret == -EAGAIN);
473 if (ret) {
474 UNLOCK_HARDWARE(vmesa);
475 fprintf(stderr, "%s: DRM_VIA_CMDBUFFER returned %d\n", __FUNCTION__, ret);
476 abort();
477 /* If this fails, the original code fell back to the PCI path.
478 */
479 }
480 else
481 return 0;
482
483 /* Fall through to PCI handling?!?
484 */
485 WAIT_IDLE(vmesa);
486 }
487
488 ret = drmCommandWrite(vmesa->driFd, DRM_VIA_PCICMD, &bufI, sizeof(bufI));
489 if (ret) {
490 UNLOCK_HARDWARE(vmesa);
491 dump_dma(vmesa);
492 fprintf(stderr, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__, ret);
493 abort();
494 }
495
496 return ret;
497 }
498
499
500 /* Inserts the surface addresss and active cliprects one at a time
501 * into the head of the DMA buffer being flushed. Fires the buffer
502 * for each cliprect.
503 */
504 static void via_emit_cliprect(viaContextPtr vmesa,
505 drm_clip_rect_t *b)
506 {
507 viaBuffer *buffer = vmesa->drawBuffer;
508 GLuint *vb = (GLuint *)(vmesa->dma + vmesa->dmaCliprectAddr);
509
510 GLuint format = (vmesa->viaScreen->bitsPerPixel == 0x20
511 ? HC_HDBFM_ARGB8888
512 : HC_HDBFM_RGB565);
513
514 GLuint pitch = buffer->pitch;
515 GLuint offset = buffer->orig;
516
517 if (0)
518 fprintf(stderr, "emit cliprect for box %d,%d %d,%d\n", b->x1, b->y1, b->x2, b->y2);
519
520 vb[0] = HC_HEADER2;
521 vb[1] = (HC_ParaType_NotTex << 16);
522
523 if (vmesa->driDrawable->w == 0 || vmesa->driDrawable->h == 0) {
524 vb[2] = (HC_SubA_HClipTB << 24) | 0x0;
525 vb[3] = (HC_SubA_HClipLR << 24) | 0x0;
526 }
527 else {
528 vb[2] = (HC_SubA_HClipTB << 24) | (b->y1 << 12) | b->y2;
529 vb[3] = (HC_SubA_HClipLR << 24) | (b->x1 << 12) | b->x2;
530 }
531
532 vb[4] = ((HC_SubA_HDBBasL << 24) | (offset & 0xFFFFFF));
533 vb[5] = ((HC_SubA_HDBBasH << 24) | ((offset & 0xFF000000)) >> 24);
534
535 /* HSPXYOS seems to be ignored on CLE266, don't emit. This is
536 * required for hardware stipple conformance (as long as we still
537 * have drawXoff).
538 */
539 if (vmesa->viaScreen->deviceID == VIA_CLE266) {
540 vb[6] = HC_DUMMY;
541 vb[7] = ((HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch);
542 }
543 else {
544 vb[6] = ((HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch);
545 vb[7] = ((HC_SubA_HSPXYOS << 24) | ((32 - vmesa->drawXoff) << HC_HSPXOS_SHIFT));
546 }
547 }
548
549
550
551 static int intersect_rect(drm_clip_rect_t *out,
552 drm_clip_rect_t *a,
553 drm_clip_rect_t *b)
554 {
555 *out = *a;
556
557 if (0)
558 fprintf(stderr, "intersect %d,%d %d,%d and %d,%d %d,%d\n",
559 a->x1, a->y1, a->x2, a->y2,
560 b->x1, b->y1, b->x2, b->y2);
561
562 if (b->x1 > out->x1) out->x1 = b->x1;
563 if (b->x2 < out->x2) out->x2 = b->x2;
564 if (out->x1 >= out->x2) return 0;
565
566 if (b->y1 > out->y1) out->y1 = b->y1;
567 if (b->y2 < out->y2) out->y2 = b->y2;
568 if (out->y1 >= out->y2) return 0;
569
570 return 1;
571 }
572
573 void viaFlushDmaLocked(viaContextPtr vmesa, GLuint flags)
574 {
575 int i;
576 RING_VARS;
577
578 if (VIA_DEBUG)
579 fprintf(stderr, "%s\n", __FUNCTION__);
580
581 if (*(GLuint *)vmesa->driHwLock != (DRM_LOCK_HELD|vmesa->hHWContext) &&
582 *(GLuint *)vmesa->driHwLock != (DRM_LOCK_HELD|DRM_LOCK_CONT|vmesa->hHWContext)) {
583 fprintf(stderr, "%s called without lock held\n", __FUNCTION__);
584 abort();
585 }
586
587 if (vmesa->dmaLow == 0) {
588 return;
589 }
590
591 assert(vmesa->dmaLastPrim == 0);
592
593 /* viaFinishPrimitive can add up to 8 bytes beyond VIA_DMA_HIGHWATER:
594 */
595 if (vmesa->dmaLow > VIA_DMA_HIGHWATER + 8) {
596 fprintf(stderr, "buffer overflow in Flush Prims = %d\n",vmesa->dmaLow);
597 abort();
598 }
599
600 switch (vmesa->dmaLow & 0x1F) {
601 case 8:
602 BEGIN_RING_NOCHECK( 6 );
603 OUT_RING( HC_HEADER2 );
604 OUT_RING( (HC_ParaType_NotTex << 16) );
605 OUT_RING( HC_DUMMY );
606 OUT_RING( HC_DUMMY );
607 OUT_RING( HC_DUMMY );
608 OUT_RING( HC_DUMMY );
609 ADVANCE_RING();
610 break;
611 case 16:
612 BEGIN_RING_NOCHECK( 4 );
613 OUT_RING( HC_HEADER2 );
614 OUT_RING( (HC_ParaType_NotTex << 16) );
615 OUT_RING( HC_DUMMY );
616 OUT_RING( HC_DUMMY );
617 ADVANCE_RING();
618 break;
619 case 24:
620 BEGIN_RING_NOCHECK( 10 );
621 OUT_RING( HC_HEADER2 );
622 OUT_RING( (HC_ParaType_NotTex << 16) );
623 OUT_RING( HC_DUMMY );
624 OUT_RING( HC_DUMMY );
625 OUT_RING( HC_DUMMY );
626 OUT_RING( HC_DUMMY );
627 OUT_RING( HC_DUMMY );
628 OUT_RING( HC_DUMMY );
629 OUT_RING( HC_DUMMY );
630 OUT_RING( HC_DUMMY );
631 ADVANCE_RING();
632 break;
633 case 0:
634 break;
635 default:
636 if (VIA_DEBUG)
637 fprintf(stderr, "%s: unaligned value for vmesa->dmaLow: %x\n",
638 __FUNCTION__, vmesa->dmaLow);
639 }
640
641
642 if (VIA_DEBUG)
643 dump_dma( vmesa );
644
645 if (flags & VIA_NO_CLIPRECTS) {
646 if (0) fprintf(stderr, "%s VIA_NO_CLIPRECTS\n", __FUNCTION__);
647 assert(vmesa->dmaCliprectAddr == ~0);
648 fire_buffer( vmesa );
649 }
650 else if (vmesa->dmaCliprectAddr == ~0) {
651 /* Contains only state. Could just dump the packet?
652 */
653 if (0) fprintf(stderr, "%s: no dmaCliprectAddr\n", __FUNCTION__);
654 if (0) fire_buffer( vmesa );
655 }
656 else if (vmesa->numClipRects) {
657 drm_clip_rect_t *pbox = vmesa->pClipRects;
658 if (0) fprintf(stderr, "%s: %d cliprects\n", __FUNCTION__, vmesa->numClipRects);
659
660 for (i = 0; i < vmesa->numClipRects; i++) {
661 drm_clip_rect_t b;
662
663 b.x1 = pbox[i].x1 - (vmesa->drawX + vmesa->drawXoff);
664 b.x2 = pbox[i].x2 - (vmesa->drawX + vmesa->drawXoff);
665 b.y1 = pbox[i].y1 - vmesa->drawY;
666 b.y2 = pbox[i].y2 - vmesa->drawY;
667
668 if (vmesa->glCtx->Scissor.Enabled &&
669 !intersect_rect(&b, &b, &vmesa->scissorRect))
670 continue;
671
672 b.x1 += vmesa->drawXoff;
673 b.x2 += vmesa->drawXoff;
674
675 via_emit_cliprect(vmesa, &b);
676
677 if (fire_buffer(vmesa) != 0) {
678 dump_dma( vmesa );
679 goto done;
680 }
681 }
682 } else {
683 if (0) fprintf(stderr, "%s: no cliprects\n", __FUNCTION__);
684 UNLOCK_HARDWARE(vmesa);
685 sched_yield();
686 LOCK_HARDWARE(vmesa);
687 }
688
689 done:
690 /* Reset vmesa vars:
691 */
692 vmesa->dmaLow = 0;
693 vmesa->dmaCliprectAddr = ~0;
694 vmesa->newEmitState = ~0;
695 }
696
697 void viaWrapPrimitive( viaContextPtr vmesa )
698 {
699 GLenum renderPrimitive = vmesa->renderPrimitive;
700 GLenum hwPrimitive = vmesa->hwPrimitive;
701
702 if (VIA_DEBUG) fprintf(stderr, "%s\n", __FUNCTION__);
703
704 if (vmesa->dmaLastPrim)
705 viaFinishPrimitive( vmesa );
706
707 viaFlushDma(vmesa);
708
709 if (renderPrimitive != GL_POLYGON + 1)
710 viaRasterPrimitive( vmesa->glCtx,
711 renderPrimitive,
712 hwPrimitive );
713
714 }
715
716 void viaFlushDma(viaContextPtr vmesa)
717 {
718 if (vmesa->dmaLow) {
719 assert(!vmesa->dmaLastPrim);
720
721 LOCK_HARDWARE(vmesa);
722 viaFlushDmaLocked(vmesa, 0);
723 UNLOCK_HARDWARE(vmesa);
724 }
725 }
726
727 static void viaFlush(GLcontext *ctx)
728 {
729 viaContextPtr vmesa = VIA_CONTEXT(ctx);
730 VIA_FLUSH_DMA(vmesa);
731 }
732
733 static void viaFinish(GLcontext *ctx)
734 {
735 viaContextPtr vmesa = VIA_CONTEXT(ctx);
736 VIA_FLUSH_DMA(vmesa);
737 WAIT_IDLE(vmesa);
738 }
739
740 static void viaClearStencil(GLcontext *ctx, int s)
741 {
742 return;
743 }
744
745 void viaInitIoctlFuncs(GLcontext *ctx)
746 {
747 ctx->Driver.Flush = viaFlush;
748 ctx->Driver.Clear = viaClear;
749 ctx->Driver.Finish = viaFinish;
750 ctx->Driver.ClearStencil = viaClearStencil;
751 }
752
753
754