1 /* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810ioctl.c,v 1.7 2002/10/30 12:51:33 alanh Exp $ */
3 #include <unistd.h> /* for usleep() */
9 #include "swrast/swrast.h"
12 #include "i810screen.h"
15 #include "i810context.h"
16 #include "i810ioctl.h"
17 #include "i810state.h"
19 static drmBufPtr
i810_get_buffer_ioctl( i810ContextPtr imesa
)
26 retcode
= drmCommandWriteRead(imesa
->driFd
, DRM_I810_GETBUF
,
27 &dma
, sizeof(drmI810DMA
));
29 if (dma
.granted
== 1 && retcode
== 0)
33 drmCommandNone(imesa
->driFd
, DRM_I810_FLUSH
);
38 buf
= &(imesa
->i810Screen
->bufs
->list
[dma
.request_idx
]);
39 buf
->idx
= dma
.request_idx
;
41 buf
->total
= dma
.request_size
;
42 buf
->address
= (drmAddress
)dma
.virtual;
49 #define DEPTH_SCALE ((1<<16)-1)
51 static void i810Clear( GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
52 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
54 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
55 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
56 const GLuint colorMask
= *((GLuint
*) &ctx
->Color
.ColorMask
);
61 clear
.clear_color
= imesa
->ClearColor
;
62 clear
.clear_depth
= (GLuint
) (ctx
->Depth
.Clear
* DEPTH_SCALE
);
64 I810_FIREVERTICES( imesa
);
66 if ((mask
& DD_FRONT_LEFT_BIT
) && colorMask
== ~0) {
67 clear
.flags
|= I810_FRONT
;
68 mask
&= ~DD_FRONT_LEFT_BIT
;
71 if ((mask
& DD_BACK_LEFT_BIT
) && colorMask
== ~0) {
72 clear
.flags
|= I810_BACK
;
73 mask
&= ~DD_BACK_LEFT_BIT
;
76 if (mask
& DD_DEPTH_BIT
) {
78 clear
.flags
|= I810_DEPTH
;
79 mask
&= ~DD_DEPTH_BIT
;
83 LOCK_HARDWARE( imesa
);
85 /* flip top to bottom */
90 for (i
= 0 ; i
< imesa
->numClipRects
; )
92 int nr
= MIN2(i
+ I810_NR_SAREA_CLIPRECTS
, imesa
->numClipRects
);
93 XF86DRIClipRectPtr box
= imesa
->pClipRects
;
94 XF86DRIClipRectPtr b
= imesa
->sarea
->boxes
;
98 for ( ; i
< nr
; i
++) {
101 GLint w
= box
[i
].x2
- x
;
102 GLint h
= box
[i
].y2
- y
;
104 if (x
< cx
) w
-= cx
- x
, x
= cx
;
105 if (y
< cy
) h
-= cy
- y
, y
= cy
;
106 if (x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
107 if (y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
108 if (w
<= 0) continue;
109 if (h
<= 0) continue;
119 for ( ; i
< nr
; i
++) {
120 *b
++ = *(XF86DRIClipRectPtr
)&box
[i
];
125 imesa
->sarea
->nbox
= n
;
126 drmCommandWrite(imesa
->driFd
, DRM_I810_CLEAR
,
127 &clear
, sizeof(drmI810Clear
));
130 UNLOCK_HARDWARE( imesa
);
131 imesa
->upload_cliprects
= GL_TRUE
;
135 _swrast_Clear( ctx
, mask
, all
, cx
, cy
, cw
, ch
);
142 * Copy the back buffer to the front buffer.
144 void i810CopyBuffer( const __DRIdrawablePrivate
*dPriv
)
146 i810ContextPtr imesa
;
147 XF86DRIClipRectPtr pbox
;
151 assert(dPriv
->driContextPriv
);
152 assert(dPriv
->driContextPriv
->driverPrivate
);
154 imesa
= (i810ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
156 I810_FIREVERTICES( imesa
);
157 LOCK_HARDWARE( imesa
);
159 pbox
= dPriv
->pClipRects
;
160 nbox
= dPriv
->numClipRects
;
162 for (i
= 0 ; i
< nbox
; )
164 int nr
= MIN2(i
+ I810_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
165 XF86DRIClipRectRec
*b
= (XF86DRIClipRectRec
*)imesa
->sarea
->boxes
;
167 imesa
->sarea
->nbox
= nr
- i
;
169 for ( ; i
< nr
; i
++)
172 drmCommandNone(imesa
->driFd
, DRM_I810_SWAP
);
175 tmp
= GET_ENQUEUE_AGE(imesa
);
176 UNLOCK_HARDWARE( imesa
);
178 /* multiarb will suck the life out of the server without this throttle:
180 if (GET_DISPATCH_AGE(imesa
) < imesa
->lastSwap
) {
181 i810WaitAge(imesa
, imesa
->lastSwap
);
184 imesa
->lastSwap
= tmp
;
185 imesa
->upload_cliprects
= GL_TRUE
;
190 * XXX implement when full-screen extension is done.
192 void i810PageFlip( const __DRIdrawablePrivate
*dPriv
)
194 i810ContextPtr imesa
;
198 assert(dPriv
->driContextPriv
);
199 assert(dPriv
->driContextPriv
->driverPrivate
);
201 imesa
= (i810ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
203 I810_FIREVERTICES( imesa
);
204 LOCK_HARDWARE( imesa
);
206 if (dPriv
->pClipRects
) {
207 *(XF86DRIClipRectRec
*)imesa
->sarea
->boxes
= dPriv
->pClipRects
[0];
208 imesa
->sarea
->nbox
= 1;
210 ret
= drmCommandNone(imesa
->driFd
, DRM_I810_FLIP
);
212 fprintf(stderr
, "%s: %d\n", __FUNCTION__
, ret
);
213 UNLOCK_HARDWARE( imesa
);
217 tmp
= GET_ENQUEUE_AGE(imesa
);
218 UNLOCK_HARDWARE( imesa
);
220 /* multiarb will suck the life out of the server without this throttle:
222 if (GET_DISPATCH_AGE(imesa
) < imesa
->lastSwap
) {
223 i810WaitAge(imesa
, imesa
->lastSwap
);
226 /* i810SetDrawBuffer( imesa->glCtx, imesa->glCtx->Color.DriverDrawBuffer );*/
227 i810DrawBuffer( imesa
->glCtx
, imesa
->glCtx
->Color
.DrawBuffer
);
228 imesa
->upload_cliprects
= GL_TRUE
;
229 imesa
->lastSwap
= tmp
;
234 /* This waits for *everybody* to finish rendering -- overkill.
236 void i810DmaFinish( i810ContextPtr imesa
)
238 I810_FIREVERTICES( imesa
);
240 LOCK_HARDWARE( imesa
);
241 i810RegetLockQuiescent( imesa
);
242 UNLOCK_HARDWARE( imesa
);
246 void i810RegetLockQuiescent( i810ContextPtr imesa
)
248 drmUnlock(imesa
->driFd
, imesa
->hHWContext
);
249 i810GetLock( imesa
, DRM_LOCK_QUIESCENT
);
252 void i810WaitAgeLocked( i810ContextPtr imesa
, int age
)
257 drmCommandNone(imesa
->driFd
, DRM_I810_GETAGE
);
258 if (GET_DISPATCH_AGE(imesa
) >= age
)
260 for (j
= 0 ; j
< 1000 ; j
++)
264 drmCommandNone(imesa
->driFd
, DRM_I810_FLUSH
);
268 void i810WaitAge( i810ContextPtr imesa
, int age
)
273 drmCommandNone(imesa
->driFd
, DRM_I810_GETAGE
);
274 if (GET_DISPATCH_AGE(imesa
) >= age
)
276 for (j
= 0 ; j
< 1000 ; j
++)
282 drmCommandNone(imesa
->driFd
, DRM_I810_GETAGE
);
283 if (GET_DISPATCH_AGE(imesa
) >= age
)
288 LOCK_HARDWARE(imesa
);
289 drmCommandNone(imesa
->driFd
, DRM_I810_FLUSH
);
290 UNLOCK_HARDWARE(imesa
);
296 static int intersect_rect( XF86DRIClipRectPtr out
,
297 XF86DRIClipRectPtr a
,
298 XF86DRIClipRectPtr b
)
301 if (b
->x1
> out
->x1
) out
->x1
= b
->x1
;
302 if (b
->x2
< out
->x2
) out
->x2
= b
->x2
;
303 if (out
->x1
>= out
->x2
) return 0;
305 if (b
->y1
> out
->y1
) out
->y1
= b
->y1
;
306 if (b
->y2
< out
->y2
) out
->y2
= b
->y2
;
307 if (out
->y1
>= out
->y2
) return 0;
312 static void emit_state( i810ContextPtr imesa
)
314 GLuint dirty
= imesa
->dirty
;
315 I810SAREAPtr sarea
= imesa
->sarea
;
317 if (dirty
& I810_UPLOAD_BUFFERS
) {
318 memcpy( sarea
->BufferState
, imesa
->BufferSetup
,
319 sizeof(imesa
->BufferSetup
) );
322 if (dirty
& I810_UPLOAD_CTX
) {
323 memcpy( sarea
->ContextState
, imesa
->Setup
,
324 sizeof(imesa
->Setup
) );
327 if (dirty
& I810_UPLOAD_TEX0
) {
328 memcpy(sarea
->TexState
[0],
329 imesa
->CurrentTexObj
[0]->Setup
,
330 sizeof(imesa
->CurrentTexObj
[0]->Setup
));
333 if (dirty
& I810_UPLOAD_TEX1
) {
334 GLuint
*setup
= sarea
->TexState
[1];
337 imesa
->CurrentTexObj
[1]->Setup
,
338 sizeof(imesa
->CurrentTexObj
[1]->Setup
));
340 /* Need this for the case where both units are bound to the same
343 setup
[I810_TEXREG_MI1
] ^= (MI1_MAP_0
^ MI1_MAP_1
);
344 setup
[I810_TEXREG_MLC
] ^= (MLC_MAP_0
^ MLC_MAP_1
);
345 setup
[I810_TEXREG_MLL
] ^= (MLL_MAP_0
^ MLL_MAP_1
);
346 setup
[I810_TEXREG_MCS
] ^= (MCS_COORD_0
^ MCS_COORD_1
);
347 setup
[I810_TEXREG_MF
] ^= (MF_MAP_0
^ MF_MAP_1
);
350 sarea
->dirty
= dirty
;
355 static void age_imesa( i810ContextPtr imesa
, int age
)
357 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->base
.timestamp
= age
;
358 if (imesa
->CurrentTexObj
[1]) imesa
->CurrentTexObj
[1]->base
.timestamp
= age
;
362 void i810FlushPrimsLocked( i810ContextPtr imesa
)
364 XF86DRIClipRectPtr pbox
= (XF86DRIClipRectPtr
)imesa
->pClipRects
;
365 int nbox
= imesa
->numClipRects
;
366 drmBufPtr buffer
= imesa
->vertex_buffer
;
367 I810SAREAPtr sarea
= imesa
->sarea
;
368 drmI810Vertex vertex
;
371 if (I810_DEBUG
& DEBUG_STATE
)
372 i810PrintDirty( __FUNCTION__
, imesa
->dirty
);
377 vertex
.idx
= buffer
->idx
;
378 vertex
.used
= imesa
->vertex_low
;
380 sarea
->vertex_prim
= imesa
->hw_primitive
;
385 else if (nbox
> I810_NR_SAREA_CLIPRECTS
) {
386 imesa
->upload_cliprects
= GL_TRUE
;
389 if (!nbox
|| !imesa
->upload_cliprects
)
397 drmCommandWrite(imesa
->driFd
, DRM_I810_VERTEX
,
398 &vertex
, sizeof(drmI810Vertex
));
399 age_imesa(imesa
, sarea
->last_enqueue
);
403 for (i
= 0 ; i
< nbox
; )
405 int nr
= MIN2(i
+ I810_NR_SAREA_CLIPRECTS
, nbox
);
406 XF86DRIClipRectPtr b
= sarea
->boxes
;
408 if (imesa
->scissor
) {
411 for ( ; i
< nr
; i
++) {
412 b
->x1
= pbox
[i
].x1
- imesa
->drawX
;
413 b
->y1
= pbox
[i
].y1
- imesa
->drawY
;
414 b
->x2
= pbox
[i
].x2
- imesa
->drawX
;
415 b
->y2
= pbox
[i
].y2
- imesa
->drawY
;
417 if (intersect_rect(b
, b
, &imesa
->scissor_rect
)) {
426 if (nr
< nbox
) continue;
430 sarea
->nbox
= nr
- i
;
431 for ( ; i
< nr
; i
++, b
++) {
432 b
->x1
= pbox
[i
].x1
- imesa
->drawX
;
433 b
->y1
= pbox
[i
].y1
- imesa
->drawY
;
434 b
->x2
= pbox
[i
].x2
- imesa
->drawX
;
435 b
->y2
= pbox
[i
].y2
- imesa
->drawY
;
439 /* Finished with the buffer?
444 drmCommandWrite(imesa
->driFd
, DRM_I810_VERTEX
,
445 &vertex
, sizeof(drmI810Vertex
));
446 age_imesa(imesa
, imesa
->sarea
->last_enqueue
);
452 imesa
->vertex_buffer
= 0;
453 imesa
->vertex_addr
= 0;
454 imesa
->vertex_low
= 0;
455 imesa
->vertex_high
= 0;
456 imesa
->vertex_last_prim
= 0;
458 imesa
->upload_cliprects
= GL_FALSE
;
461 void i810FlushPrimsGetBuffer( i810ContextPtr imesa
)
463 LOCK_HARDWARE(imesa
);
465 if (imesa
->vertex_buffer
)
466 i810FlushPrimsLocked( imesa
);
468 imesa
->vertex_buffer
= i810_get_buffer_ioctl( imesa
);
469 imesa
->vertex_high
= imesa
->vertex_buffer
->total
;
470 imesa
->vertex_addr
= (char *)imesa
->vertex_buffer
->address
;
471 imesa
->vertex_low
= 4; /* leave room for instruction header */
472 imesa
->vertex_last_prim
= imesa
->vertex_low
;
473 UNLOCK_HARDWARE(imesa
);
477 void i810FlushPrims( i810ContextPtr imesa
)
479 if (imesa
->vertex_buffer
) {
480 LOCK_HARDWARE( imesa
);
481 i810FlushPrimsLocked( imesa
);
482 UNLOCK_HARDWARE( imesa
);
488 int i810_check_copy(int fd
)
490 return(drmCommandNone(fd
, DRM_I810_DOCOPY
));
493 static void i810Flush( GLcontext
*ctx
)
495 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
496 I810_FIREVERTICES( imesa
);
499 static void i810Finish( GLcontext
*ctx
)
501 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
502 i810DmaFinish( imesa
);
505 void i810InitIoctlFuncs( GLcontext
*ctx
)
507 ctx
->Driver
.Flush
= i810Flush
;
508 ctx
->Driver
.Clear
= i810Clear
;
509 ctx
->Driver
.Finish
= i810Finish
;