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
)
53 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
54 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
55 const GLuint colorMask
= *((GLuint
*) &ctx
->Color
.ColorMask
);
60 clear
.clear_color
= imesa
->ClearColor
;
61 clear
.clear_depth
= (GLuint
) (ctx
->Depth
.Clear
* DEPTH_SCALE
);
63 I810_FIREVERTICES( imesa
);
65 if ((mask
& BUFFER_BIT_FRONT_LEFT
) && colorMask
== ~0U) {
66 clear
.flags
|= I810_FRONT
;
67 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
70 if ((mask
& BUFFER_BIT_BACK_LEFT
) && colorMask
== ~0U) {
71 clear
.flags
|= I810_BACK
;
72 mask
&= ~BUFFER_BIT_BACK_LEFT
;
75 if (mask
& BUFFER_BIT_DEPTH
) {
77 clear
.flags
|= I810_DEPTH
;
78 mask
&= ~BUFFER_BIT_DEPTH
;
84 LOCK_HARDWARE( imesa
);
86 /* compute region after locking: */
87 cx
= ctx
->DrawBuffer
->_Xmin
;
88 cy
= ctx
->DrawBuffer
->_Ymin
;
89 cw
= ctx
->DrawBuffer
->_Xmax
- cx
;
90 ch
= ctx
->DrawBuffer
->_Ymax
- cy
;
92 /* flip top to bottom */
97 for (i
= 0 ; i
< imesa
->numClipRects
; )
99 unsigned int nr
= MIN2(i
+ I810_NR_SAREA_CLIPRECTS
, imesa
->numClipRects
);
100 drm_clip_rect_t
*box
= imesa
->pClipRects
;
101 drm_clip_rect_t
*b
= (drm_clip_rect_t
*)imesa
->sarea
->boxes
;
104 if (cw
!= dPriv
->w
|| ch
!= dPriv
->h
) {
105 /* clear sub region */
106 for ( ; i
< nr
; i
++) {
109 GLint w
= box
[i
].x2
- x
;
110 GLint h
= box
[i
].y2
- y
;
112 if (x
< cx
) w
-= cx
- x
, x
= cx
;
113 if (y
< cy
) h
-= cy
- y
, y
= cy
;
114 if (x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
115 if (y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
116 if (w
<= 0) continue;
117 if (h
<= 0) continue;
127 /* clear whole buffer */
128 for ( ; i
< nr
; i
++) {
134 imesa
->sarea
->nbox
= n
;
135 drmCommandWrite(imesa
->driFd
, DRM_I810_CLEAR
,
136 &clear
, sizeof(drmI810Clear
));
139 UNLOCK_HARDWARE( imesa
);
140 imesa
->upload_cliprects
= GL_TRUE
;
144 _swrast_Clear( ctx
, mask
);
151 * Copy the back buffer to the front buffer.
153 void i810CopyBuffer( const __DRIdrawablePrivate
*dPriv
)
155 i810ContextPtr imesa
;
156 drm_clip_rect_t
*pbox
;
160 assert(dPriv
->driContextPriv
);
161 assert(dPriv
->driContextPriv
->driverPrivate
);
163 imesa
= (i810ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
165 I810_FIREVERTICES( imesa
);
166 LOCK_HARDWARE( imesa
);
168 pbox
= (drm_clip_rect_t
*)dPriv
->pClipRects
;
169 nbox
= dPriv
->numClipRects
;
171 for (i
= 0 ; i
< nbox
; )
173 int nr
= MIN2(i
+ I810_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
174 drm_clip_rect_t
*b
= (drm_clip_rect_t
*)imesa
->sarea
->boxes
;
176 imesa
->sarea
->nbox
= nr
- i
;
178 for ( ; i
< nr
; i
++)
181 drmCommandNone(imesa
->driFd
, DRM_I810_SWAP
);
184 tmp
= GET_ENQUEUE_AGE(imesa
);
185 UNLOCK_HARDWARE( imesa
);
187 /* multiarb will suck the life out of the server without this throttle:
189 if (GET_DISPATCH_AGE(imesa
) < imesa
->lastSwap
) {
190 i810WaitAge(imesa
, imesa
->lastSwap
);
193 imesa
->lastSwap
= tmp
;
194 imesa
->upload_cliprects
= GL_TRUE
;
199 * XXX implement when full-screen extension is done.
201 void i810PageFlip( const __DRIdrawablePrivate
*dPriv
)
203 i810ContextPtr imesa
;
207 assert(dPriv
->driContextPriv
);
208 assert(dPriv
->driContextPriv
->driverPrivate
);
210 imesa
= (i810ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
212 I810_FIREVERTICES( imesa
);
213 LOCK_HARDWARE( imesa
);
215 if (dPriv
->pClipRects
) {
216 memcpy(&(imesa
->sarea
->boxes
[0]), &(dPriv
->pClipRects
[0]),
217 sizeof(drm_clip_rect_t
));
218 imesa
->sarea
->nbox
= 1;
220 ret
= drmCommandNone(imesa
->driFd
, DRM_I810_FLIP
);
222 fprintf(stderr
, "%s: %d\n", __FUNCTION__
, ret
);
223 UNLOCK_HARDWARE( imesa
);
227 tmp
= GET_ENQUEUE_AGE(imesa
);
228 UNLOCK_HARDWARE( imesa
);
230 /* multiarb will suck the life out of the server without this throttle:
232 if (GET_DISPATCH_AGE(imesa
) < imesa
->lastSwap
) {
233 i810WaitAge(imesa
, imesa
->lastSwap
);
236 /* i810SetDrawBuffer( imesa->glCtx, imesa->glCtx->Color.DriverDrawBuffer );*/
237 i810DrawBuffer( imesa
->glCtx
, imesa
->glCtx
->Color
.DrawBuffer
[0] );
238 imesa
->upload_cliprects
= GL_TRUE
;
239 imesa
->lastSwap
= tmp
;
244 /* This waits for *everybody* to finish rendering -- overkill.
246 void i810DmaFinish( i810ContextPtr imesa
)
248 I810_FIREVERTICES( imesa
);
250 LOCK_HARDWARE( imesa
);
251 i810RegetLockQuiescent( imesa
);
252 UNLOCK_HARDWARE( imesa
);
256 void i810RegetLockQuiescent( i810ContextPtr imesa
)
258 drmUnlock(imesa
->driFd
, imesa
->hHWContext
);
259 i810GetLock( imesa
, DRM_LOCK_QUIESCENT
);
262 void i810WaitAgeLocked( i810ContextPtr imesa
, int age
)
267 drmCommandNone(imesa
->driFd
, DRM_I810_GETAGE
);
268 if (GET_DISPATCH_AGE(imesa
) >= age
)
270 for (j
= 0 ; j
< 1000 ; j
++)
274 drmCommandNone(imesa
->driFd
, DRM_I810_FLUSH
);
278 void i810WaitAge( i810ContextPtr imesa
, int age
)
283 drmCommandNone(imesa
->driFd
, DRM_I810_GETAGE
);
284 if (GET_DISPATCH_AGE(imesa
) >= age
)
286 for (j
= 0 ; j
< 1000 ; j
++)
292 drmCommandNone(imesa
->driFd
, DRM_I810_GETAGE
);
293 if (GET_DISPATCH_AGE(imesa
) >= age
)
298 LOCK_HARDWARE(imesa
);
299 drmCommandNone(imesa
->driFd
, DRM_I810_FLUSH
);
300 UNLOCK_HARDWARE(imesa
);
306 static int intersect_rect( drm_clip_rect_t
*out
,
311 if (b
->x1
> out
->x1
) out
->x1
= b
->x1
;
312 if (b
->x2
< out
->x2
) out
->x2
= b
->x2
;
313 if (out
->x1
>= out
->x2
) return 0;
315 if (b
->y1
> out
->y1
) out
->y1
= b
->y1
;
316 if (b
->y2
< out
->y2
) out
->y2
= b
->y2
;
317 if (out
->y1
>= out
->y2
) return 0;
322 static void emit_state( i810ContextPtr imesa
)
324 GLuint dirty
= imesa
->dirty
;
325 I810SAREAPtr sarea
= imesa
->sarea
;
327 if (dirty
& I810_UPLOAD_BUFFERS
) {
328 memcpy( sarea
->BufferState
, imesa
->BufferSetup
,
329 sizeof(imesa
->BufferSetup
) );
332 if (dirty
& I810_UPLOAD_CTX
) {
333 memcpy( sarea
->ContextState
, imesa
->Setup
,
334 sizeof(imesa
->Setup
) );
337 if (dirty
& I810_UPLOAD_TEX0
) {
338 memcpy(sarea
->TexState
[0],
339 imesa
->CurrentTexObj
[0]->Setup
,
340 sizeof(imesa
->CurrentTexObj
[0]->Setup
));
343 if (dirty
& I810_UPLOAD_TEX1
) {
344 GLuint
*setup
= sarea
->TexState
[1];
347 imesa
->CurrentTexObj
[1]->Setup
,
348 sizeof(imesa
->CurrentTexObj
[1]->Setup
));
350 /* Need this for the case where both units are bound to the same
353 setup
[I810_TEXREG_MI1
] ^= (MI1_MAP_0
^ MI1_MAP_1
);
354 setup
[I810_TEXREG_MLC
] ^= (MLC_MAP_0
^ MLC_MAP_1
);
355 setup
[I810_TEXREG_MLL
] ^= (MLL_MAP_0
^ MLL_MAP_1
);
356 setup
[I810_TEXREG_MCS
] ^= (MCS_COORD_0
^ MCS_COORD_1
);
357 setup
[I810_TEXREG_MF
] ^= (MF_MAP_0
^ MF_MAP_1
);
360 sarea
->dirty
= dirty
;
365 static void age_imesa( i810ContextPtr imesa
, int age
)
367 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->base
.timestamp
= age
;
368 if (imesa
->CurrentTexObj
[1]) imesa
->CurrentTexObj
[1]->base
.timestamp
= age
;
372 void i810FlushPrimsLocked( i810ContextPtr imesa
)
374 drm_clip_rect_t
*pbox
= imesa
->pClipRects
;
375 int nbox
= imesa
->numClipRects
;
376 drmBufPtr buffer
= imesa
->vertex_buffer
;
377 I810SAREAPtr sarea
= imesa
->sarea
;
378 drmI810Vertex vertex
;
381 if (I810_DEBUG
& DEBUG_STATE
)
382 i810PrintDirty( __FUNCTION__
, imesa
->dirty
);
387 vertex
.idx
= buffer
->idx
;
388 vertex
.used
= imesa
->vertex_low
;
390 sarea
->vertex_prim
= imesa
->hw_primitive
;
395 else if (nbox
> I810_NR_SAREA_CLIPRECTS
) {
396 imesa
->upload_cliprects
= GL_TRUE
;
399 if (!nbox
|| !imesa
->upload_cliprects
)
407 drmCommandWrite(imesa
->driFd
, DRM_I810_VERTEX
,
408 &vertex
, sizeof(drmI810Vertex
));
409 age_imesa(imesa
, sarea
->last_enqueue
);
413 for (i
= 0 ; i
< nbox
; )
415 int nr
= MIN2(i
+ I810_NR_SAREA_CLIPRECTS
, nbox
);
416 drm_clip_rect_t
*b
= (drm_clip_rect_t
*)sarea
->boxes
;
418 if (imesa
->scissor
) {
421 for ( ; i
< nr
; i
++) {
422 b
->x1
= pbox
[i
].x1
- imesa
->drawX
;
423 b
->y1
= pbox
[i
].y1
- imesa
->drawY
;
424 b
->x2
= pbox
[i
].x2
- imesa
->drawX
;
425 b
->y2
= pbox
[i
].y2
- imesa
->drawY
;
427 if (intersect_rect(b
, b
, &imesa
->scissor_rect
)) {
436 if (nr
< nbox
) continue;
440 sarea
->nbox
= nr
- i
;
441 for ( ; i
< nr
; i
++, b
++) {
442 b
->x1
= pbox
[i
].x1
- imesa
->drawX
;
443 b
->y1
= pbox
[i
].y1
- imesa
->drawY
;
444 b
->x2
= pbox
[i
].x2
- imesa
->drawX
;
445 b
->y2
= pbox
[i
].y2
- imesa
->drawY
;
449 /* Finished with the buffer?
454 drmCommandWrite(imesa
->driFd
, DRM_I810_VERTEX
,
455 &vertex
, sizeof(drmI810Vertex
));
456 age_imesa(imesa
, imesa
->sarea
->last_enqueue
);
462 imesa
->vertex_buffer
= 0;
463 imesa
->vertex_addr
= 0;
464 imesa
->vertex_low
= 0;
465 imesa
->vertex_high
= 0;
466 imesa
->vertex_last_prim
= 0;
468 imesa
->upload_cliprects
= GL_FALSE
;
471 void i810FlushPrimsGetBuffer( i810ContextPtr imesa
)
473 LOCK_HARDWARE(imesa
);
475 if (imesa
->vertex_buffer
)
476 i810FlushPrimsLocked( imesa
);
478 imesa
->vertex_buffer
= i810_get_buffer_ioctl( imesa
);
479 imesa
->vertex_high
= imesa
->vertex_buffer
->total
;
480 imesa
->vertex_addr
= (char *)imesa
->vertex_buffer
->address
;
481 imesa
->vertex_low
= 4; /* leave room for instruction header */
482 imesa
->vertex_last_prim
= imesa
->vertex_low
;
483 UNLOCK_HARDWARE(imesa
);
487 void i810FlushPrims( i810ContextPtr imesa
)
489 if (imesa
->vertex_buffer
) {
490 LOCK_HARDWARE( imesa
);
491 i810FlushPrimsLocked( imesa
);
492 UNLOCK_HARDWARE( imesa
);
498 int i810_check_copy(int fd
)
500 return(drmCommandNone(fd
, DRM_I810_DOCOPY
));
503 static void i810Flush( GLcontext
*ctx
)
505 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
506 I810_FIREVERTICES( imesa
);
509 static void i810Finish( GLcontext
*ctx
)
511 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
512 i810DmaFinish( imesa
);
515 void i810InitIoctlFuncs( struct dd_function_table
*functions
)
517 functions
->Flush
= i810Flush
;
518 functions
->Clear
= i810Clear
;
519 functions
->Finish
= i810Finish
;