7e7b933becbea9ce153ccb714c15d78ba035cc42
[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 /* HSPXYOS seems to be ignored on CLE266, don't emit. This is
546 * required for hardware stipple conformance (as long as we still
547 * have drawXoff).
548 */
549 if (vmesa->viaScreen->deviceID == VIA_CLE266) {
550 vb[6] = HC_DUMMY;
551 vb[7] = ((HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch);
552 }
553 else {
554 vb[6] = ((HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch);
555 vb[7] = ((HC_SubA_HSPXYOS << 24) | ((32 - vmesa->drawXoff) << HC_HSPXOS_SHIFT));
556 }
557 }
558
559
560
561 static int intersect_rect(drm_clip_rect_t *out,
562 drm_clip_rect_t *a,
563 drm_clip_rect_t *b)
564 {
565 *out = *a;
566
567 if (0)
568 fprintf(stderr, "intersect %d,%d %d,%d and %d,%d %d,%d\n",
569 a->x1, a->y1, a->x2, a->y2,
570 b->x1, b->y1, b->x2, b->y2);
571
572 if (b->x1 > out->x1) out->x1 = b->x1;
573 if (b->x2 < out->x2) out->x2 = b->x2;
574 if (out->x1 >= out->x2) return 0;
575
576 if (b->y1 > out->y1) out->y1 = b->y1;
577 if (b->y2 < out->y2) out->y2 = b->y2;
578 if (out->y1 >= out->y2) return 0;
579
580 return 1;
581 }
582
583 void viaFlushDmaLocked(viaContextPtr vmesa, GLuint flags)
584 {
585 int i;
586 RING_VARS;
587
588 if (VIA_DEBUG)
589 fprintf(stderr, "%s\n", __FUNCTION__);
590
591 if (*(GLuint *)vmesa->driHwLock != (DRM_LOCK_HELD|vmesa->hHWContext) &&
592 *(GLuint *)vmesa->driHwLock != (DRM_LOCK_HELD|DRM_LOCK_CONT|vmesa->hHWContext)) {
593 fprintf(stderr, "%s called without lock held\n", __FUNCTION__);
594 abort();
595 }
596
597 if (vmesa->dmaLow == 0) {
598 return;
599 }
600
601 assert(vmesa->dmaLastPrim == 0);
602
603 /* viaFinishPrimitive can add up to 8 bytes beyond VIA_DMA_HIGHWATER:
604 */
605 if (vmesa->dmaLow > VIA_DMA_HIGHWATER + 8) {
606 fprintf(stderr, "buffer overflow in Flush Prims = %d\n",vmesa->dmaLow);
607 abort();
608 }
609
610 switch (vmesa->dmaLow & 0x1F) {
611 case 8:
612 BEGIN_RING_NOCHECK( 6 );
613 OUT_RING( HC_HEADER2 );
614 OUT_RING( (HC_ParaType_NotTex << 16) );
615 OUT_RING( HC_DUMMY );
616 OUT_RING( HC_DUMMY );
617 OUT_RING( HC_DUMMY );
618 OUT_RING( HC_DUMMY );
619 ADVANCE_RING();
620 break;
621 case 16:
622 BEGIN_RING_NOCHECK( 4 );
623 OUT_RING( HC_HEADER2 );
624 OUT_RING( (HC_ParaType_NotTex << 16) );
625 OUT_RING( HC_DUMMY );
626 OUT_RING( HC_DUMMY );
627 ADVANCE_RING();
628 break;
629 case 24:
630 BEGIN_RING_NOCHECK( 10 );
631 OUT_RING( HC_HEADER2 );
632 OUT_RING( (HC_ParaType_NotTex << 16) );
633 OUT_RING( HC_DUMMY );
634 OUT_RING( HC_DUMMY );
635 OUT_RING( HC_DUMMY );
636 OUT_RING( HC_DUMMY );
637 OUT_RING( HC_DUMMY );
638 OUT_RING( HC_DUMMY );
639 OUT_RING( HC_DUMMY );
640 OUT_RING( HC_DUMMY );
641 ADVANCE_RING();
642 break;
643 case 0:
644 break;
645 default:
646 if (VIA_DEBUG)
647 fprintf(stderr, "%s: unaligned value for vmesa->dmaLow: %x\n",
648 __FUNCTION__, vmesa->dmaLow);
649 }
650
651
652 if (VIA_DEBUG)
653 dump_dma( vmesa );
654
655 if (flags & VIA_NO_CLIPRECTS) {
656 if (0) fprintf(stderr, "%s VIA_NO_CLIPRECTS\n", __FUNCTION__);
657 assert(vmesa->dmaCliprectAddr == ~0);
658 fire_buffer( vmesa );
659 }
660 else if (vmesa->dmaCliprectAddr == ~0) {
661 /* Contains only state. Could just dump the packet?
662 */
663 if (0) fprintf(stderr, "%s: no dmaCliprectAddr\n", __FUNCTION__);
664 if (0) fire_buffer( vmesa );
665 }
666 else if (vmesa->numClipRects) {
667 drm_clip_rect_t *pbox = vmesa->pClipRects;
668 if (0) fprintf(stderr, "%s: %d cliprects\n", __FUNCTION__, vmesa->numClipRects);
669
670 for (i = 0; i < vmesa->numClipRects; i++) {
671 drm_clip_rect_t b;
672
673 b.x1 = pbox[i].x1 - (vmesa->drawX + vmesa->drawXoff);
674 b.x2 = pbox[i].x2 - (vmesa->drawX + vmesa->drawXoff);
675 b.y1 = pbox[i].y1 - vmesa->drawY;
676 b.y2 = pbox[i].y2 - vmesa->drawY;
677
678 if (vmesa->scissor &&
679 !intersect_rect(&b, &b, &vmesa->scissorRect))
680 continue;
681
682 b.x1 += vmesa->drawXoff;
683 b.x2 += vmesa->drawXoff;
684
685 via_emit_cliprect(vmesa, &b);
686
687 if (fire_buffer(vmesa) != 0) {
688 dump_dma( vmesa );
689 goto done;
690 }
691 }
692 } else {
693 if (0) fprintf(stderr, "%s: no cliprects\n", __FUNCTION__);
694 UNLOCK_HARDWARE(vmesa);
695 sched_yield();
696 LOCK_HARDWARE(vmesa);
697 }
698
699 done:
700 /* Reset vmesa vars:
701 */
702 vmesa->dmaLow = 0;
703 vmesa->dmaCliprectAddr = ~0;
704 vmesa->newEmitState = ~0;
705 }
706
707 void viaWrapPrimitive( viaContextPtr vmesa )
708 {
709 GLenum renderPrimitive = vmesa->renderPrimitive;
710 GLenum hwPrimitive = vmesa->hwPrimitive;
711
712 if (VIA_DEBUG) fprintf(stderr, "%s\n", __FUNCTION__);
713
714 if (vmesa->dmaLastPrim)
715 viaFinishPrimitive( vmesa );
716
717 viaFlushDma(vmesa);
718
719 if (renderPrimitive != GL_POLYGON + 1)
720 viaRasterPrimitive( vmesa->glCtx,
721 renderPrimitive,
722 hwPrimitive );
723
724 }
725
726 void viaFlushDma(viaContextPtr vmesa)
727 {
728 if (vmesa->dmaLow) {
729 assert(!vmesa->dmaLastPrim);
730
731 LOCK_HARDWARE(vmesa);
732 viaFlushDmaLocked(vmesa, 0);
733 UNLOCK_HARDWARE(vmesa);
734 }
735 }
736
737 static void viaFlush(GLcontext *ctx)
738 {
739 viaContextPtr vmesa = VIA_CONTEXT(ctx);
740 VIA_FLUSH_DMA(vmesa);
741 }
742
743 static void viaFinish(GLcontext *ctx)
744 {
745 viaContextPtr vmesa = VIA_CONTEXT(ctx);
746 VIA_FLUSH_DMA(vmesa);
747 WAIT_IDLE(vmesa);
748 }
749
750 static void viaClearStencil(GLcontext *ctx, int s)
751 {
752 return;
753 }
754
755 void viaInitIoctlFuncs(GLcontext *ctx)
756 {
757 ctx->Driver.Flush = viaFlush;
758 ctx->Driver.Clear = viaClear;
759 ctx->Driver.Finish = viaFinish;
760 ctx->Driver.ClearStencil = viaClearStencil;
761 }
762
763
764