2 #include <unistd.h> /* for usleep() */
4 #include "main/glheader.h"
5 #include "main/mtypes.h"
6 #include "main/macros.h"
8 #include "swrast/swrast.h"
11 #include "i810screen.h"
14 #include "main/context.h"
15 #include "i810ioctl.h"
16 #include "i810state.h"
18 static drmBufPtr
i810_get_buffer_ioctl( i810ContextPtr imesa
)
25 retcode
= drmCommandWriteRead(imesa
->driFd
, DRM_I810_GETBUF
,
26 &dma
, sizeof(drmI810DMA
));
28 if (dma
.granted
== 1 && retcode
== 0)
32 drmCommandNone(imesa
->driFd
, DRM_I810_FLUSH
);
37 buf
= &(imesa
->i810Screen
->bufs
->list
[dma
.request_idx
]);
38 buf
->idx
= dma
.request_idx
;
40 buf
->total
= dma
.request_size
;
41 buf
->address
= (drmAddress
)dma
.virtual;
48 #define DEPTH_SCALE ((1<<16)-1)
50 static void i810Clear( GLcontext
*ctx
, GLbitfield mask
)
52 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
53 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
54 const GLuint colorMask
= *((GLuint
*) &ctx
->Color
.ColorMask
);
59 clear
.clear_color
= imesa
->ClearColor
;
60 clear
.clear_depth
= (GLuint
) (ctx
->Depth
.Clear
* DEPTH_SCALE
);
62 I810_FIREVERTICES( imesa
);
64 if ((mask
& BUFFER_BIT_FRONT_LEFT
) && colorMask
== ~0U) {
65 clear
.flags
|= I810_FRONT
;
66 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
69 if ((mask
& BUFFER_BIT_BACK_LEFT
) && colorMask
== ~0U) {
70 clear
.flags
|= I810_BACK
;
71 mask
&= ~BUFFER_BIT_BACK_LEFT
;
74 if (mask
& BUFFER_BIT_DEPTH
) {
76 clear
.flags
|= I810_DEPTH
;
77 mask
&= ~BUFFER_BIT_DEPTH
;
83 LOCK_HARDWARE( imesa
);
85 /* compute region after locking: */
86 cx
= ctx
->DrawBuffer
->_Xmin
;
87 cy
= ctx
->DrawBuffer
->_Ymin
;
88 cw
= ctx
->DrawBuffer
->_Xmax
- cx
;
89 ch
= ctx
->DrawBuffer
->_Ymax
- cy
;
91 /* flip top to bottom */
96 for (i
= 0 ; i
< imesa
->numClipRects
; )
98 unsigned int nr
= MIN2(i
+ I810_NR_SAREA_CLIPRECTS
, imesa
->numClipRects
);
99 drm_clip_rect_t
*box
= imesa
->pClipRects
;
100 drm_clip_rect_t
*b
= (drm_clip_rect_t
*)imesa
->sarea
->boxes
;
103 if (cw
!= dPriv
->w
|| ch
!= dPriv
->h
) {
104 /* clear sub region */
105 for ( ; i
< nr
; i
++) {
108 GLint w
= box
[i
].x2
- x
;
109 GLint h
= box
[i
].y2
- y
;
111 if (x
< cx
) w
-= cx
- x
, x
= cx
;
112 if (y
< cy
) h
-= cy
- y
, y
= cy
;
113 if (x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
114 if (y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
115 if (w
<= 0) continue;
116 if (h
<= 0) continue;
126 /* clear whole buffer */
127 for ( ; i
< nr
; i
++) {
133 imesa
->sarea
->nbox
= n
;
134 drmCommandWrite(imesa
->driFd
, DRM_I810_CLEAR
,
135 &clear
, sizeof(drmI810Clear
));
138 UNLOCK_HARDWARE( imesa
);
139 imesa
->upload_cliprects
= GL_TRUE
;
143 _swrast_Clear( ctx
, mask
);
150 * Copy the back buffer to the front buffer.
152 void i810CopyBuffer( const __DRIdrawablePrivate
*dPriv
)
154 i810ContextPtr imesa
;
155 drm_clip_rect_t
*pbox
;
159 assert(dPriv
->driContextPriv
);
160 assert(dPriv
->driContextPriv
->driverPrivate
);
162 imesa
= (i810ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
164 I810_FIREVERTICES( imesa
);
165 LOCK_HARDWARE( imesa
);
167 pbox
= (drm_clip_rect_t
*)dPriv
->pClipRects
;
168 nbox
= dPriv
->numClipRects
;
170 for (i
= 0 ; i
< nbox
; )
172 int nr
= MIN2(i
+ I810_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
173 drm_clip_rect_t
*b
= (drm_clip_rect_t
*)imesa
->sarea
->boxes
;
175 imesa
->sarea
->nbox
= nr
- i
;
177 for ( ; i
< nr
; i
++)
180 drmCommandNone(imesa
->driFd
, DRM_I810_SWAP
);
183 tmp
= GET_ENQUEUE_AGE(imesa
);
184 UNLOCK_HARDWARE( imesa
);
186 /* multiarb will suck the life out of the server without this throttle:
188 if (GET_DISPATCH_AGE(imesa
) < imesa
->lastSwap
) {
189 i810WaitAge(imesa
, imesa
->lastSwap
);
192 imesa
->lastSwap
= tmp
;
193 imesa
->upload_cliprects
= GL_TRUE
;
198 * XXX implement when full-screen extension is done.
200 void i810PageFlip( const __DRIdrawablePrivate
*dPriv
)
202 i810ContextPtr imesa
;
206 assert(dPriv
->driContextPriv
);
207 assert(dPriv
->driContextPriv
->driverPrivate
);
209 imesa
= (i810ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
211 I810_FIREVERTICES( imesa
);
212 LOCK_HARDWARE( imesa
);
214 if (dPriv
->pClipRects
) {
215 memcpy(&(imesa
->sarea
->boxes
[0]), &(dPriv
->pClipRects
[0]),
216 sizeof(drm_clip_rect_t
));
217 imesa
->sarea
->nbox
= 1;
219 ret
= drmCommandNone(imesa
->driFd
, DRM_I810_FLIP
);
221 fprintf(stderr
, "%s: %d\n", __FUNCTION__
, ret
);
222 UNLOCK_HARDWARE( imesa
);
226 tmp
= GET_ENQUEUE_AGE(imesa
);
227 UNLOCK_HARDWARE( imesa
);
229 /* multiarb will suck the life out of the server without this throttle:
231 if (GET_DISPATCH_AGE(imesa
) < imesa
->lastSwap
) {
232 i810WaitAge(imesa
, imesa
->lastSwap
);
235 /* i810SetDrawBuffer( imesa->glCtx, imesa->glCtx->Color.DriverDrawBuffer );*/
236 i810DrawBuffer( imesa
->glCtx
, imesa
->glCtx
->Color
.DrawBuffer
[0] );
237 imesa
->upload_cliprects
= GL_TRUE
;
238 imesa
->lastSwap
= tmp
;
243 /* This waits for *everybody* to finish rendering -- overkill.
245 void i810DmaFinish( i810ContextPtr imesa
)
247 I810_FIREVERTICES( imesa
);
249 LOCK_HARDWARE( imesa
);
250 i810RegetLockQuiescent( imesa
);
251 UNLOCK_HARDWARE( imesa
);
255 void i810RegetLockQuiescent( i810ContextPtr imesa
)
257 drmUnlock(imesa
->driFd
, imesa
->hHWContext
);
258 i810GetLock( imesa
, DRM_LOCK_QUIESCENT
);
261 void i810WaitAgeLocked( i810ContextPtr imesa
, int age
)
266 drmCommandNone(imesa
->driFd
, DRM_I810_GETAGE
);
267 if (GET_DISPATCH_AGE(imesa
) >= age
)
269 for (j
= 0 ; j
< 1000 ; j
++)
273 drmCommandNone(imesa
->driFd
, DRM_I810_FLUSH
);
277 void i810WaitAge( i810ContextPtr imesa
, int age
)
282 drmCommandNone(imesa
->driFd
, DRM_I810_GETAGE
);
283 if (GET_DISPATCH_AGE(imesa
) >= age
)
285 for (j
= 0 ; j
< 1000 ; j
++)
291 drmCommandNone(imesa
->driFd
, DRM_I810_GETAGE
);
292 if (GET_DISPATCH_AGE(imesa
) >= age
)
297 LOCK_HARDWARE(imesa
);
298 drmCommandNone(imesa
->driFd
, DRM_I810_FLUSH
);
299 UNLOCK_HARDWARE(imesa
);
305 static int intersect_rect( drm_clip_rect_t
*out
,
310 if (b
->x1
> out
->x1
) out
->x1
= b
->x1
;
311 if (b
->x2
< out
->x2
) out
->x2
= b
->x2
;
312 if (out
->x1
>= out
->x2
) return 0;
314 if (b
->y1
> out
->y1
) out
->y1
= b
->y1
;
315 if (b
->y2
< out
->y2
) out
->y2
= b
->y2
;
316 if (out
->y1
>= out
->y2
) return 0;
321 static void emit_state( i810ContextPtr imesa
)
323 GLuint dirty
= imesa
->dirty
;
324 I810SAREAPtr sarea
= imesa
->sarea
;
326 if (dirty
& I810_UPLOAD_BUFFERS
) {
327 memcpy( sarea
->BufferState
, imesa
->BufferSetup
,
328 sizeof(imesa
->BufferSetup
) );
331 if (dirty
& I810_UPLOAD_CTX
) {
332 memcpy( sarea
->ContextState
, imesa
->Setup
,
333 sizeof(imesa
->Setup
) );
336 if (dirty
& I810_UPLOAD_TEX0
) {
337 memcpy(sarea
->TexState
[0],
338 imesa
->CurrentTexObj
[0]->Setup
,
339 sizeof(imesa
->CurrentTexObj
[0]->Setup
));
342 if (dirty
& I810_UPLOAD_TEX1
) {
343 GLuint
*setup
= sarea
->TexState
[1];
346 imesa
->CurrentTexObj
[1]->Setup
,
347 sizeof(imesa
->CurrentTexObj
[1]->Setup
));
349 /* Need this for the case where both units are bound to the same
352 setup
[I810_TEXREG_MI1
] ^= (MI1_MAP_0
^ MI1_MAP_1
);
353 setup
[I810_TEXREG_MLC
] ^= (MLC_MAP_0
^ MLC_MAP_1
);
354 setup
[I810_TEXREG_MLL
] ^= (MLL_MAP_0
^ MLL_MAP_1
);
355 setup
[I810_TEXREG_MCS
] ^= (MCS_COORD_0
^ MCS_COORD_1
);
356 setup
[I810_TEXREG_MF
] ^= (MF_MAP_0
^ MF_MAP_1
);
359 sarea
->dirty
= dirty
;
364 static void age_imesa( i810ContextPtr imesa
, int age
)
366 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->base
.timestamp
= age
;
367 if (imesa
->CurrentTexObj
[1]) imesa
->CurrentTexObj
[1]->base
.timestamp
= age
;
371 void i810FlushPrimsLocked( i810ContextPtr imesa
)
373 drm_clip_rect_t
*pbox
= imesa
->pClipRects
;
374 int nbox
= imesa
->numClipRects
;
375 drmBufPtr buffer
= imesa
->vertex_buffer
;
376 I810SAREAPtr sarea
= imesa
->sarea
;
377 drmI810Vertex vertex
;
380 if (I810_DEBUG
& DEBUG_STATE
)
381 i810PrintDirty( __FUNCTION__
, imesa
->dirty
);
386 vertex
.idx
= buffer
->idx
;
387 vertex
.used
= imesa
->vertex_low
;
389 sarea
->vertex_prim
= imesa
->hw_primitive
;
394 else if (nbox
> I810_NR_SAREA_CLIPRECTS
) {
395 imesa
->upload_cliprects
= GL_TRUE
;
398 if (!nbox
|| !imesa
->upload_cliprects
)
406 drmCommandWrite(imesa
->driFd
, DRM_I810_VERTEX
,
407 &vertex
, sizeof(drmI810Vertex
));
408 age_imesa(imesa
, sarea
->last_enqueue
);
412 for (i
= 0 ; i
< nbox
; )
414 int nr
= MIN2(i
+ I810_NR_SAREA_CLIPRECTS
, nbox
);
415 drm_clip_rect_t
*b
= (drm_clip_rect_t
*)sarea
->boxes
;
417 if (imesa
->scissor
) {
420 for ( ; i
< nr
; i
++) {
421 b
->x1
= pbox
[i
].x1
- imesa
->drawX
;
422 b
->y1
= pbox
[i
].y1
- imesa
->drawY
;
423 b
->x2
= pbox
[i
].x2
- imesa
->drawX
;
424 b
->y2
= pbox
[i
].y2
- imesa
->drawY
;
426 if (intersect_rect(b
, b
, &imesa
->scissor_rect
)) {
435 if (nr
< nbox
) continue;
439 sarea
->nbox
= nr
- i
;
440 for ( ; i
< nr
; i
++, b
++) {
441 b
->x1
= pbox
[i
].x1
- imesa
->drawX
;
442 b
->y1
= pbox
[i
].y1
- imesa
->drawY
;
443 b
->x2
= pbox
[i
].x2
- imesa
->drawX
;
444 b
->y2
= pbox
[i
].y2
- imesa
->drawY
;
448 /* Finished with the buffer?
453 drmCommandWrite(imesa
->driFd
, DRM_I810_VERTEX
,
454 &vertex
, sizeof(drmI810Vertex
));
455 age_imesa(imesa
, imesa
->sarea
->last_enqueue
);
461 imesa
->vertex_buffer
= 0;
462 imesa
->vertex_addr
= 0;
463 imesa
->vertex_low
= 0;
464 imesa
->vertex_high
= 0;
465 imesa
->vertex_last_prim
= 0;
467 imesa
->upload_cliprects
= GL_FALSE
;
470 void i810FlushPrimsGetBuffer( i810ContextPtr imesa
)
472 LOCK_HARDWARE(imesa
);
474 if (imesa
->vertex_buffer
)
475 i810FlushPrimsLocked( imesa
);
477 imesa
->vertex_buffer
= i810_get_buffer_ioctl( imesa
);
478 imesa
->vertex_high
= imesa
->vertex_buffer
->total
;
479 imesa
->vertex_addr
= (char *)imesa
->vertex_buffer
->address
;
480 imesa
->vertex_low
= 4; /* leave room for instruction header */
481 imesa
->vertex_last_prim
= imesa
->vertex_low
;
482 UNLOCK_HARDWARE(imesa
);
486 void i810FlushPrims( i810ContextPtr imesa
)
488 if (imesa
->vertex_buffer
) {
489 LOCK_HARDWARE( imesa
);
490 i810FlushPrimsLocked( imesa
);
491 UNLOCK_HARDWARE( imesa
);
497 int i810_check_copy(int fd
)
499 return(drmCommandNone(fd
, DRM_I810_DOCOPY
));
502 static void i810Flush( GLcontext
*ctx
)
504 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
505 I810_FIREVERTICES( imesa
);
508 static void i810Finish( GLcontext
*ctx
)
510 i810ContextPtr imesa
= I810_CONTEXT( ctx
);
511 i810DmaFinish( imesa
);
514 void i810InitIoctlFuncs( struct dd_function_table
*functions
)
516 functions
->Flush
= i810Flush
;
517 functions
->Clear
= i810Clear
;
518 functions
->Finish
= i810Finish
;