e90ec0f78e4723c8990948d81c684261116630ae
[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 /* 16bpp doesn't support masked clears */
247 if (vmesa->viaScreen->bytesPerPixel == 2 &&
248 vmesa->ClearMask & 0xf0000000) {
249 if (flag & VIA_FRONT)
250 mask |= DD_FRONT_LEFT_BIT;
251 if (flag & VIA_BACK)
252 mask |= DD_BACK_LEFT_BIT;
253 flag &= ~(VIA_FRONT | VIA_BACK);
254 }
255
256 if (flag) {
257 drm_clip_rect_t *boxes, *tmp_boxes = 0;
258 int nr = 0;
259
260 LOCK_HARDWARE(vmesa);
261
262 /* flip top to bottom */
263 cy = dPriv->h - cy - ch;
264 cx += vmesa->drawX + vmesa->drawXoff;
265 cy += vmesa->drawY;
266
267 if (!all) {
268 drm_clip_rect_t *b = vmesa->pClipRects;
269
270 boxes = tmp_boxes = (drm_clip_rect_t *)malloc(vmesa->numClipRects *
271 sizeof(drm_clip_rect_t));
272 if (!boxes) {
273 UNLOCK_HARDWARE(vmesa);
274 return;
275 }
276
277 for (; i < vmesa->numClipRects; i++) {
278 GLint x = b[i].x1;
279 GLint y = b[i].y1;
280 GLint w = b[i].x2 - x;
281 GLint h = b[i].y2 - y;
282
283 if (x < cx) w -= cx - x, x = cx;
284 if (y < cy) h -= cy - y, y = cy;
285 if (x + w > cx + cw) w = cx + cw - x;
286 if (y + h > cy + ch) h = cy + ch - y;
287 if (w <= 0) continue;
288 if (h <= 0) continue;
289
290 boxes[nr].x1 = x;
291 boxes[nr].y1 = y;
292 boxes[nr].x2 = x + w;
293 boxes[nr].y2 = y + h;
294 nr++;
295 }
296 }
297 else {
298 boxes = vmesa->pClipRects;
299 nr = vmesa->numClipRects;
300 }
301
302 if (flag & VIA_FRONT) {
303 viaFillBuffer(vmesa, &vmesa->front, boxes, nr, vmesa->ClearColor, vmesa->ClearMask);
304 }
305
306 if (flag & VIA_BACK) {
307 viaFillBuffer(vmesa, &vmesa->back, boxes, nr, vmesa->ClearColor, vmesa->ClearMask);
308 }
309
310 if (flag & VIA_DEPTH) {
311 viaFillBuffer(vmesa, &vmesa->depth, boxes, nr, clear_depth, clear_depth_mask);
312 }
313
314 viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS);
315 UNLOCK_HARDWARE(vmesa);
316
317 if (tmp_boxes)
318 free(tmp_boxes);
319 }
320
321 if (mask)
322 _swrast_Clear(ctx, mask, all, cx, cy, cw, ch);
323 }
324
325
326
327
328 static void viaDoSwapBuffers(viaContextPtr vmesa,
329 drm_clip_rect_t *b,
330 GLuint nbox)
331 {
332 GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
333 viaBuffer *front = &vmesa->front;
334 viaBuffer *back = &vmesa->back;
335 GLuint i;
336
337 for (i = 0; i < nbox; i++, b++) {
338 GLint x = b->x1 - vmesa->drawX;
339 GLint y = b->y1 - vmesa->drawY;
340 GLint w = b->x2 - b->x1;
341 GLint h = b->y2 - b->y1;
342
343 GLuint src = back->orig + y * back->pitch + x * bytePerPixel;
344 GLuint dest = front->orig + y * front->pitch + x * bytePerPixel;
345
346 viaBlit(vmesa,
347 bytePerPixel << 3,
348 src, back->pitch,
349 dest, front->pitch,
350 w, h,
351 VIA_BLIT_COPY, 0, 0);
352 }
353 }
354
355
356
357
358 /*
359 * Copy the back buffer to the front buffer.
360 */
361 void viaCopyBuffer(const __DRIdrawablePrivate *dPriv)
362 {
363 viaContextPtr vmesa = (viaContextPtr)dPriv->driContextPriv->driverPrivate;
364 GLboolean missed_target;
365
366 VIA_FLUSH_DMA(vmesa);
367 driWaitForVBlank( dPriv, & vmesa->vbl_seq, vmesa->vblank_flags, & missed_target );
368 if ( missed_target ) {
369 vmesa->swap_missed_count++;
370 vmesa->get_ust( &vmesa->swap_missed_ust );
371 }
372 LOCK_HARDWARE(vmesa);
373
374 viaDoSwapBuffers(vmesa, dPriv->pClipRects, dPriv->numClipRects);
375 viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS);
376
377 UNLOCK_HARDWARE(vmesa);
378 vmesa->swap_count++;
379 vmesa->get_ust( &vmesa->swap_ust );
380 }
381
382 /*
383 * XXX implement when full-screen extension is done.
384 */
385 void viaPageFlip(const __DRIdrawablePrivate *dPriv)
386 {
387 viaContextPtr vmesa = (viaContextPtr)dPriv->driContextPriv->driverPrivate;
388 viaBuffer buffer_tmp;
389 GLboolean missed_target;
390
391
392 VIA_FLUSH_DMA(vmesa);
393 driWaitForVBlank( dPriv, &vmesa->vbl_seq, vmesa->vblank_flags, &missed_target );
394 if ( missed_target ) {
395 vmesa->swap_missed_count++;
396 vmesa->get_ust( &vmesa->swap_missed_ust );
397 }
398 LOCK_HARDWARE(vmesa);
399
400 {
401 RING_VARS;
402
403 if (!vmesa->nDoneFirstFlip) {
404 vmesa->nDoneFirstFlip = GL_FALSE; /* XXX: FIXME LATER!!! */
405 BEGIN_RING(4);
406 OUT_RING(HALCYON_HEADER2);
407 OUT_RING(0x00fe0000);
408 OUT_RING(0x0000000e);
409 OUT_RING(0x0000000e);
410 ADVANCE_RING();
411 }
412
413 BEGIN_RING(4);
414 OUT_RING( HALCYON_HEADER2 );
415 OUT_RING( 0x00fe0000 );
416 OUT_RING((HC_SubA_HFBBasL << 24) | (vmesa->back.offset & 0xFFFFF8) | 0x2);
417 OUT_RING((HC_SubA_HFBDrawFirst << 24) |
418 ((vmesa->back.offset & 0xFF000000) >> 24) | 0x0100);
419 ADVANCE_RING();
420
421 }
422
423 viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS);
424 UNLOCK_HARDWARE(vmesa);
425 vmesa->swap_count++;
426 vmesa->get_ust( &vmesa->swap_ust );
427
428 /* KW: FIXME: When buffers are freed, could free frontbuffer by
429 * accident:
430 */
431 memcpy(&buffer_tmp, &vmesa->back, sizeof(viaBuffer));
432 memcpy(&vmesa->back, &vmesa->front, sizeof(viaBuffer));
433 memcpy(&vmesa->front, &buffer_tmp, sizeof(viaBuffer));
434
435 if(vmesa->currentPage) {
436 vmesa->currentPage = 0;
437 }
438 else {
439 vmesa->currentPage = 1;
440 }
441
442 if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__);
443 }
444
445
446
447
448 #define VIA_CMDBUF_MAX_LAG 50000
449
450 static int fire_buffer(viaContextPtr vmesa)
451 {
452 drm_via_cmdbuffer_t bufI;
453 int ret;
454
455 bufI.buf = (char *)vmesa->dma;
456 bufI.size = vmesa->dmaLow;
457
458 if (vmesa->useAgp) {
459 drm_via_cmdbuf_size_t bSiz;
460
461 /* Do the CMDBUF_SIZE ioctl:
462 */
463 bSiz.func = VIA_CMDBUF_LAG;
464 bSiz.wait = 1;
465 bSiz.size = VIA_CMDBUF_MAX_LAG;
466 do {
467 ret = drmCommandWriteRead(vmesa->driFd, DRM_VIA_CMDBUF_SIZE,
468 &bSiz, sizeof(bSiz));
469 } while (ret == -EAGAIN);
470 if (ret) {
471 UNLOCK_HARDWARE(vmesa);
472 fprintf(stderr, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n", __FUNCTION__, ret);
473 abort();
474 return ret;
475 }
476
477 /* Actually fire the buffer:
478 */
479 do {
480 ret = drmCommandWrite(vmesa->driFd, DRM_VIA_CMDBUFFER,
481 &bufI, sizeof(bufI));
482 } while (ret == -EAGAIN);
483 if (ret) {
484 UNLOCK_HARDWARE(vmesa);
485 fprintf(stderr, "%s: DRM_VIA_CMDBUFFER returned %d\n", __FUNCTION__, ret);
486 abort();
487 /* If this fails, the original code fell back to the PCI path.
488 */
489 }
490 else
491 return 0;
492
493 /* Fall through to PCI handling?!?
494 */
495 WAIT_IDLE(vmesa);
496 }
497
498 ret = drmCommandWrite(vmesa->driFd, DRM_VIA_PCICMD, &bufI, sizeof(bufI));
499 if (ret) {
500 UNLOCK_HARDWARE(vmesa);
501 dump_dma(vmesa);
502 fprintf(stderr, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__, ret);
503 abort();
504 }
505
506 return ret;
507 }
508
509
510 /* Inserts the surface addresss and active cliprects one at a time
511 * into the head of the DMA buffer being flushed. Fires the buffer
512 * for each cliprect.
513 */
514 static void via_emit_cliprect(viaContextPtr vmesa,
515 drm_clip_rect_t *b)
516 {
517 viaBuffer *buffer = vmesa->drawBuffer;
518 GLuint *vb = (GLuint *)(vmesa->dma + vmesa->dmaCliprectAddr);
519
520 GLuint format = (vmesa->viaScreen->bitsPerPixel == 0x20
521 ? HC_HDBFM_ARGB8888
522 : HC_HDBFM_RGB565);
523
524 GLuint pitch = buffer->pitch;
525 GLuint offset = buffer->orig;
526
527 if (0)
528 fprintf(stderr, "emit cliprect for box %d,%d %d,%d\n", b->x1, b->y1, b->x2, b->y2);
529
530 vb[0] = HC_HEADER2;
531 vb[1] = (HC_ParaType_NotTex << 16);
532
533 if (vmesa->driDrawable->w == 0 || vmesa->driDrawable->h == 0) {
534 vb[2] = (HC_SubA_HClipTB << 24) | 0x0;
535 vb[3] = (HC_SubA_HClipLR << 24) | 0x0;
536 }
537 else {
538 vb[2] = (HC_SubA_HClipTB << 24) | (b->y1 << 12) | b->y2;
539 vb[3] = (HC_SubA_HClipLR << 24) | (b->x1 << 12) | b->x2;
540 }
541
542 vb[4] = ((HC_SubA_HDBBasL << 24) | (offset & 0xFFFFFF));
543 vb[5] = ((HC_SubA_HDBBasH << 24) | ((offset & 0xFF000000)) >> 24);
544
545 vb[6] = ((HC_SubA_HSPXYOS << 24) | ((31 - vmesa->drawXoff) << HC_HSPXOS_SHIFT));
546 vb[7] = ((HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch);
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->scissor &&
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