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 drm_clip_rect_t
*box
= imesa
->pClipRects
;
94 drm_clip_rect_t
*b
= (drm_clip_rect_t
*)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
++) {
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 drm_clip_rect_t
*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
= (drm_clip_rect_t
*)dPriv
->pClipRects
;
160 nbox
= dPriv
->numClipRects
;
162 for (i
= 0 ; i
< nbox
; )
164 int nr
= MIN2(i
+ I810_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
165 drm_clip_rect_t
*b
= (drm_clip_rect_t
*)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 memcpy(&(imesa
->sarea
->boxes
[0]), &(dPriv
->pClipRects
[0]),
208 sizeof(drm_clip_rect_t
));
209 imesa
->sarea
->nbox
= 1;
211 ret
= drmCommandNone(imesa
->driFd
, DRM_I810_FLIP
);
213 fprintf(stderr
, "%s: %d\n", __FUNCTION__
, ret
);
214 UNLOCK_HARDWARE( imesa
);
218 tmp
= GET_ENQUEUE_AGE(imesa
);
219 UNLOCK_HARDWARE( imesa
);
221 /* multiarb will suck the life out of the server without this throttle:
223 if (GET_DISPATCH_AGE(imesa
) < imesa
->lastSwap
) {
224 i810WaitAge(imesa
, imesa
->lastSwap
);
227 /* i810SetDrawBuffer( imesa->glCtx, imesa->glCtx->Color.DriverDrawBuffer );*/
228 i810DrawBuffer( imesa
->glCtx
, imesa
->glCtx
->Color
.DrawBuffer
[0] );
229 imesa
->upload_cliprects
= GL_TRUE
;
230 imesa
->lastSwap
= tmp
;
235 /* This waits for *everybody* to finish rendering -- overkill.
237 void i810DmaFinish( i810ContextPtr imesa
)
239 I810_FIREVERTICES( imesa
);
241 LOCK_HARDWARE( imesa
);
242 i810RegetLockQuiescent( imesa
);
243 UNLOCK_HARDWARE( imesa
);
247 void i810RegetLockQuiescent( i810ContextPtr imesa
)
249 drmUnlock(imesa
->driFd
, imesa
->hHWContext
);
250 i810GetLock( imesa
, DRM_LOCK_QUIESCENT
);
253 void i810WaitAgeLocked( i810ContextPtr imesa
, int age
)
258 drmCommandNone(imesa
->driFd
, DRM_I810_GETAGE
);
259 if (GET_DISPATCH_AGE(imesa
) >= age
)
261 for (j
= 0 ; j
< 1000 ; j
++)
265 drmCommandNone(imesa
->driFd
, DRM_I810_FLUSH
);
269 void i810WaitAge( i810ContextPtr imesa
, int age
)
274 drmCommandNone(imesa
->driFd
, DRM_I810_GETAGE
);
275 if (GET_DISPATCH_AGE(imesa
) >= age
)
277 for (j
= 0 ; j
< 1000 ; j
++)
283 drmCommandNone(imesa
->driFd
, DRM_I810_GETAGE
);
284 if (GET_DISPATCH_AGE(imesa
) >= age
)
289 LOCK_HARDWARE(imesa
);
290 drmCommandNone(imesa
->driFd
, DRM_I810_FLUSH
);
291 UNLOCK_HARDWARE(imesa
);
297 static int intersect_rect( drm_clip_rect_t
*out
,
302 if (b
->x1
> out
->x1
) out
->x1
= b
->x1
;
303 if (b
->x2
< out
->x2
) out
->x2
= b
->x2
;
304 if (out
->x1
>= out
->x2
) return 0;
306 if (b
->y1
> out
->y1
) out
->y1
= b
->y1
;
307 if (b
->y2
< out
->y2
) out
->y2
= b
->y2
;
308 if (out
->y1
>= out
->y2
) return 0;
313 static void emit_state( i810ContextPtr imesa
)
315 GLuint dirty
= imesa
->dirty
;
316 I810SAREAPtr sarea
= imesa
->sarea
;
318 if (dirty
& I810_UPLOAD_BUFFERS
) {
319 memcpy( sarea
->BufferState
, imesa
->BufferSetup
,
320 sizeof(imesa
->BufferSetup
) );
323 if (dirty
& I810_UPLOAD_CTX
) {
324 memcpy( sarea
->ContextState
, imesa
->Setup
,
325 sizeof(imesa
->Setup
) );
328 if (dirty
& I810_UPLOAD_TEX0
) {
329 memcpy(sarea
->TexState
[0],
330 imesa
->CurrentTexObj
[0]->Setup
,
331 sizeof(imesa
->CurrentTexObj
[0]->Setup
));
334 if (dirty
& I810_UPLOAD_TEX1
) {
335 GLuint
*setup
= sarea
->TexState
[1];
338 imesa
->CurrentTexObj
[1]->Setup
,
339 sizeof(imesa
->CurrentTexObj
[1]->Setup
));
341 /* Need this for the case where both units are bound to the same
344 setup
[I810_TEXREG_MI1
] ^= (MI1_MAP_0
^ MI1_MAP_1
);
345 setup
[I810_TEXREG_MLC
] ^= (MLC_MAP_0
^ MLC_MAP_1
);
346 setup
[I810_TEXREG_MLL
] ^= (MLL_MAP_0
^ MLL_MAP_1
);
347 setup
[I810_TEXREG_MCS
] ^= (MCS_COORD_0
^ MCS_COORD_1
);
348 setup
[I810_TEXREG_MF
] ^= (MF_MAP_0
^ MF_MAP_1
);
351 sarea
->dirty
= dirty
;
356 static void age_imesa( i810ContextPtr imesa
, int age
)
358 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->base
.timestamp
= age
;
359 if (imesa
->CurrentTexObj
[1]) imesa
->CurrentTexObj
[1]->base
.timestamp
= age
;
363 void i810FlushPrimsLocked( i810ContextPtr imesa
)
365 drm_clip_rect_t
*pbox
= imesa
->pClipRects
;
366 int nbox
= imesa
->numClipRects
;
367 drmBufPtr buffer
= imesa
->vertex_buffer
;
368 I810SAREAPtr sarea
= imesa
->sarea
;
369 drmI810Vertex vertex
;
372 if (I810_DEBUG
& DEBUG_STATE
)
373 i810PrintDirty( __FUNCTION__
, imesa
->dirty
);
378 vertex
.idx
= buffer
->idx
;
379 vertex
.used
= imesa
->vertex_low
;
381 sarea
->vertex_prim
= imesa
->hw_primitive
;
386 else if (nbox
> I810_NR_SAREA_CLIPRECTS
) {
387 imesa
->upload_cliprects
= GL_TRUE
;
390 if (!nbox
|| !imesa
->upload_cliprects
)
398 drmCommandWrite(imesa
->driFd
, DRM_I810_VERTEX
,
399 &vertex
, sizeof(drmI810Vertex
));
400 age_imesa(imesa
, sarea
->last_enqueue
);
404 for (i
= 0 ; i
< nbox
; )
406 int nr
= MIN2(i
+ I810_NR_SAREA_CLIPRECTS
, nbox
);
407 drm_clip_rect_t
*b
= (drm_clip_rect_t
*)sarea
->boxes
;
409 if (imesa
->scissor
) {
412 for ( ; i
< nr
; i
++) {
413 b
->x1
= pbox
[i
].x1
- imesa
->drawX
;
414 b
->y1
= pbox
[i
].y1
- imesa
->drawY
;
415 b
->x2
= pbox
[i
].x2
- imesa
->drawX
;
416 b
->y2
= pbox
[i
].y2
- imesa
->drawY
;
418 if (intersect_rect(b
, b
, &imesa
->scissor_rect
)) {
427 if (nr
< nbox
) continue;
431 sarea
->nbox
= nr
- i
;
432 for ( ; i
< nr
; i
++, b
++) {
433 b
->x1
= pbox
[i
].x1
- imesa
->drawX
;
434 b
->y1
= pbox
[i
].y1
- imesa
->drawY
;
435 b
->x2
= pbox
[i
].x2
- imesa
->drawX
;
436 b
->y2
= pbox
[i
].y2
- imesa
->drawY
;
440 /* Finished with the buffer?
445 drmCommandWrite(imesa
->driFd
, DRM_I810_VERTEX
,
446 &vertex
, sizeof(drmI810Vertex
));
447 age_imesa(imesa
, imesa
->sarea
->last_enqueue
);
453 imesa
->vertex_buffer
= 0;
454 imesa
->vertex_addr
= 0;
455 imesa
->vertex_low
= 0;
456 imesa
->vertex_high
= 0;
457 imesa
->vertex_last_prim
= 0;
459 imesa
->upload_cliprects
= GL_FALSE
;
462 void i810FlushPrimsGetBuffer( i810ContextPtr imesa
)
464 LOCK_HARDWARE(imesa
);
466 if (imesa
->vertex_buffer
)
467 i810FlushPrimsLocked( imesa
);
469 imesa
->vertex_buffer
= i810_get_buffer_ioctl( imesa
);
470 imesa
->vertex_high
= imesa
->vertex_buffer
->total
;
471 imesa
->vertex_addr
= (char *)imesa
->vertex_buffer
->address
;
472 imesa
->vertex_low
= 4; /* leave room for instruction header */
473 imesa
->vertex_last_prim
= imesa
->vertex_low
;
474 UNLOCK_HARDWARE(imesa
);
478 void i810FlushPrims( i810ContextPtr imesa
)
480 if (imesa
->vertex_buffer
) {
481 LOCK_HARDWARE( imesa
);
482 i810FlushPrimsLocked( imesa
);
483 UNLOCK_HARDWARE( imesa
);
489 int i810_check_copy(int fd
)
491 return(drmCommandNone(fd
, DRM_I810_DOCOPY
));
494 static void i810Flush( GLcontext
*ctx
)
496 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
497 I810_FIREVERTICES( imesa
);
500 static void i810Finish( GLcontext
*ctx
)
502 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
503 i810DmaFinish( imesa
);
506 void i810InitIoctlFuncs( struct dd_function_table
*functions
)
508 functions
->Flush
= i810Flush
;
509 functions
->Clear
= i810Clear
;
510 functions
->Finish
= i810Finish
;