2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
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:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
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.
34 #include "swrast/swrast.h"
37 #include "savagecontext.h"
38 #include "savageioctl.h"
39 #include "savage_bci.h"
40 #include "savagedma.h"
43 #include <sys/ioctl.h>
44 #include <sys/timeb.h>
46 extern GLuint bcicount
;
47 #define DEPTH_SCALE_16 ((1<<16)-1)
48 #define DEPTH_SCALE_24 ((1<<24)-1)
50 static void savage_BCI_clear(GLcontext
*ctx
, drm_savage_clear_t
*pclear
)
52 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
53 int nbox
= imesa
->sarea
->nbox
;
54 drm_clip_rect_t
*pbox
= imesa
->sarea
->boxes
;
58 if (nbox
> SAVAGE_NR_SAREA_CLIPRECTS
)
59 nbox
= SAVAGE_NR_SAREA_CLIPRECTS
;
61 for (i
= 0 ; i
< nbox
; i
++, pbox
++) {
62 unsigned int x
= pbox
->x1
;
63 unsigned int y
= pbox
->y1
;
64 unsigned int width
= pbox
->x2
- x
;
65 unsigned int height
= pbox
->y2
- y
;
68 if (pbox
->x1
> pbox
->x2
||
69 pbox
->y1
> pbox
->y2
||
70 pbox
->x2
> imesa
->savageScreen
->width
||
71 pbox
->y2
> imesa
->savageScreen
->height
)
74 if ( pclear
->flags
& SAVAGE_FRONT
) {
75 bciptr
= savageDMAAlloc (imesa
, 8);
76 WRITE_CMD((bciptr
) , 0x4BCC8C00,uint32_t);
77 WRITE_CMD((bciptr
) , imesa
->savageScreen
->frontOffset
,uint32_t);
78 WRITE_CMD((bciptr
) , imesa
->savageScreen
->frontBitmapDesc
,uint32_t);
79 WRITE_CMD((bciptr
) , pclear
->clear_color
,uint32_t);
80 WRITE_CMD((bciptr
) , (y
<<16) | x
,uint32_t);
81 WRITE_CMD((bciptr
) , (height
<< 16) | width
,uint32_t);
82 savageDMACommit (imesa
, bciptr
);
84 if ( pclear
->flags
& SAVAGE_BACK
) {
85 bciptr
= savageDMAAlloc (imesa
, 8);
86 WRITE_CMD((bciptr
) , 0x4BCC8C00,uint32_t);
87 WRITE_CMD((bciptr
) , imesa
->savageScreen
->backOffset
,uint32_t);
88 WRITE_CMD((bciptr
) , imesa
->savageScreen
->backBitmapDesc
,uint32_t);
89 WRITE_CMD((bciptr
) , pclear
->clear_color
,uint32_t);
90 WRITE_CMD((bciptr
) , (y
<<16) | x
,uint32_t);
91 WRITE_CMD((bciptr
) , (height
<< 16) | width
,uint32_t);
92 savageDMACommit (imesa
, bciptr
);
95 if ( pclear
->flags
& (SAVAGE_DEPTH
|SAVAGE_STENCIL
) ) {
96 uint32_t writeMask
= 0x0;
99 if(pclear
->flags
& SAVAGE_STENCIL
)
102 writeMask
|= 0xFF000000;
104 if(pclear
->flags
& SAVAGE_DEPTH
)
106 writeMask
|= 0x00FFFFFF;
109 if(imesa
->IsFullScreen
&& imesa
->NotFirstFrame
&&
110 imesa
->savageScreen
->chipset
>= S3_SAVAGE4
)
112 imesa
->regs
.s4
.zBufCtrl
.ni
.autoZEnable
= GL_TRUE
;
113 imesa
->regs
.s4
.zBufCtrl
.ni
.frameID
=
114 ~imesa
->regs
.s4
.zBufCtrl
.ni
.frameID
;
116 imesa
->dirty
|= SAVAGE_UPLOAD_CTX
;
120 if(imesa
->IsFullScreen
)
121 imesa
->NotFirstFrame
= GL_TRUE
;
123 if(imesa
->hw_stencil
)
125 bciptr
= savageDMAAlloc (imesa
, 10);
126 if(writeMask
!= 0xFFFFFFFF)
128 WRITE_CMD((bciptr
) , 0x960100D7,uint32_t);
129 WRITE_CMD((bciptr
) , writeMask
,uint32_t);
134 bciptr
= savageDMAAlloc (imesa
, 6);
137 WRITE_CMD((bciptr
) , 0x4BCC8C00,uint32_t);
138 WRITE_CMD((bciptr
) , imesa
->savageScreen
->depthOffset
,uint32_t);
139 WRITE_CMD((bciptr
) , imesa
->savageScreen
->depthBitmapDesc
,uint32_t);
140 WRITE_CMD((bciptr
) , pclear
->clear_depth
,uint32_t);
141 WRITE_CMD((bciptr
) , (y
<<16) | x
,uint32_t);
142 WRITE_CMD((bciptr
) , (height
<< 16) | width
,uint32_t);
143 if(imesa
->hw_stencil
)
145 if(writeMask
!= 0xFFFFFFFF)
147 WRITE_CMD((bciptr
) , 0x960100D7,uint32_t);
148 WRITE_CMD((bciptr
) , 0xFFFFFFFF,uint32_t);
151 savageDMACommit (imesa
, bciptr
);
155 /* FK: Make sure that the clear stuff is emitted. Otherwise a
156 software fallback may get overwritten by a delayed clear. */
157 savageDMAFlush (imesa
);
162 static void savage_BCI_swap(savageContextPtr imesa
)
164 int nbox
= imesa
->sarea
->nbox
;
165 drm_clip_rect_t
*pbox
= imesa
->sarea
->boxes
;
167 volatile uint32_t *bciptr
;
169 if (nbox
> SAVAGE_NR_SAREA_CLIPRECTS
)
170 nbox
= SAVAGE_NR_SAREA_CLIPRECTS
;
171 savageDMAFlush (imesa
);
173 if(imesa
->IsFullScreen
)
176 tmp0
= imesa
->savageScreen
->frontOffset
;
177 imesa
->savageScreen
->frontOffset
= imesa
->savageScreen
->backOffset
;
178 imesa
->savageScreen
->backOffset
= tmp0
;
180 if(imesa
->toggle
== TARGET_BACK
)
181 imesa
->toggle
= TARGET_FRONT
;
183 imesa
->toggle
= TARGET_BACK
;
185 imesa
->drawMap
= (char *)imesa
->apertureBase
[imesa
->toggle
];
186 imesa
->readMap
= (char *)imesa
->apertureBase
[imesa
->toggle
];
188 imesa
->regs
.s4
.destCtrl
.ni
.offset
= imesa
->savageScreen
->backOffset
>>11;
189 imesa
->dirty
|= SAVAGE_UPLOAD_CTX
;
190 bciptr
= SAVAGE_GET_BCI_POINTER(imesa
,3);
191 *(bciptr
) = 0x960100B0;
192 *(bciptr
) = (imesa
->savageScreen
->frontOffset
);
193 *(bciptr
) = 0xA0000000;
197 { /* Use bitblt copy from back to front buffer*/
199 for (i
= 0 ; i
< nbox
; i
++, pbox
++)
201 unsigned int w
= pbox
->x2
- pbox
->x1
;
202 unsigned int h
= pbox
->y2
- pbox
->y1
;
204 if (pbox
->x1
> pbox
->x2
||
205 pbox
->y1
> pbox
->y2
||
206 pbox
->x2
> imesa
->savageScreen
->width
||
207 pbox
->y2
> imesa
->savageScreen
->height
)
210 bciptr
= SAVAGE_GET_BCI_POINTER(imesa
,6);
212 *(bciptr
) = 0x4BCC00C0;
214 *(bciptr
) = imesa
->savageScreen
->backOffset
;
215 *(bciptr
) = imesa
->savageScreen
->backBitmapDesc
;
216 *(bciptr
) = (pbox
->y1
<<16) | pbox
->x1
; /*x0, y0*/
217 *(bciptr
) = (pbox
->y1
<<16) | pbox
->x1
;
218 *(bciptr
) = (h
<< 16) | w
;
225 static void savageDDClear( GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
226 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
228 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
229 __DRIdrawablePrivate
*dPriv
= imesa
->driDrawable
;
230 const GLuint colorMask
= *((GLuint
*) &ctx
->Color
.ColorMask
);
231 drm_savage_clear_t clear
;
235 clear
.clear_color
= imesa
->ClearColor
;
237 if(imesa
->savageScreen
->zpp
== 2)
238 clear
.clear_depth
= (GLuint
) (ctx
->Depth
.Clear
* DEPTH_SCALE_16
);
240 clear
.clear_depth
= (GLuint
) (ctx
->Depth
.Clear
* DEPTH_SCALE_24
);
242 FLUSH_BATCH( imesa
);
244 if ((mask
& DD_FRONT_LEFT_BIT
) && ((colorMask
&0xffffffUL
)==0xffffffUL
) ){
245 clear
.flags
|= SAVAGE_FRONT
;
246 mask
&= ~DD_FRONT_LEFT_BIT
;
249 if ((mask
& DD_BACK_LEFT_BIT
) && ((colorMask
&0xffffffUL
)==0xffffffUL
) ) {
250 clear
.flags
|= SAVAGE_BACK
;
251 mask
&= ~DD_BACK_LEFT_BIT
;
254 if ((mask
& DD_DEPTH_BIT
) && ctx
->Depth
.Mask
) {
255 clear
.flags
|= SAVAGE_DEPTH
;
256 mask
&= ~DD_DEPTH_BIT
;
259 if((mask
& DD_STENCIL_BIT
) && imesa
->hw_stencil
)
261 clear
.flags
|= SAVAGE_STENCIL
;
262 mask
&= ~DD_STENCIL_BIT
;
266 LOCK_HARDWARE( imesa
);
268 /* flip top to bottom */
273 for (i
= 0 ; i
< imesa
->numClipRects
; ) {
274 int nr
= MIN2(i
+ SAVAGE_NR_SAREA_CLIPRECTS
, imesa
->numClipRects
);
275 drm_clip_rect_t
*box
= imesa
->pClipRects
;
276 drm_clip_rect_t
*b
= imesa
->sarea
->boxes
;
280 for ( ; i
< nr
; i
++) {
283 GLint w
= box
[i
].x2
- x
;
284 GLint h
= box
[i
].y2
- y
;
286 if (x
< cx
) w
-= cx
- x
, x
= cx
;
287 if (y
< cy
) h
-= cy
- y
, y
= cy
;
288 if (x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
289 if (y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
290 if (w
<= 0) continue;
291 if (h
<= 0) continue;
301 for ( ; i
< nr
; i
++) {
302 *b
++ = *(drm_clip_rect_t
*)&box
[i
];
307 imesa
->sarea
->nbox
= n
;
309 savage_BCI_clear(ctx
,&clear
);
312 UNLOCK_HARDWARE( imesa
);
313 imesa
->dirty
|= SAVAGE_UPLOAD_CLIPRECTS
|SAVAGE_UPLOAD_CTX
;
317 _swrast_Clear( ctx
, mask
, all
, cx
, cy
, cw
, ch
);
324 * Copy the back buffer to the front buffer.
326 void savageSwapBuffers( __DRIdrawablePrivate
*dPriv
)
328 savageContextPtr imesa
;
329 drm_clip_rect_t
*pbox
;
336 assert(dPriv
->driContextPriv
);
337 assert(dPriv
->driContextPriv
->driverPrivate
);
339 imesa
= (savageContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
341 _mesa_notifySwapBuffers( imesa
->glCtx
);
345 LOCK_HARDWARE( imesa
);
347 PAGE_PENDING(pending
);
351 pbox
= dPriv
->pClipRects
;
352 nbox
= dPriv
->numClipRects
;
354 for (i
= 0 ; i
< nbox
; )
356 int nr
= MIN2(i
+ SAVAGE_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
357 drm_clip_rect_t
*b
= (drm_clip_rect_t
*)imesa
->sarea
->boxes
;
359 imesa
->sarea
->nbox
= nr
- i
;
361 for ( ; i
< nr
; i
++)
363 savage_BCI_swap(imesa
) ;
366 UNLOCK_HARDWARE( imesa
);
371 /* This waits for *everybody* to finish rendering -- overkill.
373 void savageDmaFinish( savageContextPtr imesa
)
375 savageDMAFlush(imesa
);
380 void savageRegetLockQuiescent( savageContextPtr imesa
)
386 void savageWaitAgeLocked( savageContextPtr imesa
, int age
)
391 void savageWaitAge( savageContextPtr imesa
, int age
)
397 void savageFlushVerticesLocked( savageContextPtr imesa
)
399 drmBufPtr buffer
= imesa
->vertex_dma_buffer
;
404 imesa
->vertex_dma_buffer
= NULL
;
406 /* Lot's of stuff to do here. For now there is a fake DMA implementation
407 * in savagedma.c that emits drawing commands. Cliprects are not handled
410 /* State must be updated "per primitive" because hardware
411 * culling must be disabled for unfilled primitives, points
413 savageEmitHwStateLocked (imesa
);
414 savageFakeVertices (imesa
, buffer
);
419 void savageFlushVertices( savageContextPtr imesa
)
421 LOCK_HARDWARE(imesa
);
422 savageFlushVerticesLocked (imesa
);
423 UNLOCK_HARDWARE(imesa
);
427 int savage_check_copy(int fd
)
432 static void savageDDFlush( GLcontext
*ctx
)
434 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
435 LOCK_HARDWARE(imesa
);
436 savageFlushVerticesLocked (imesa
);
437 savageDMAFlush (imesa
);
438 UNLOCK_HARDWARE(imesa
);
441 static void savageDDFinish( GLcontext
*ctx
)
443 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
444 LOCK_HARDWARE(imesa
);
445 savageFlushVerticesLocked (imesa
);
446 savageDmaFinish (imesa
);
447 UNLOCK_HARDWARE(imesa
);
450 #define ALT_STATUS_WORD0 (* (volatile GLuint *)(imesa->MMIO_BASE+0x48c60))
451 #define STATUS_WORD0 (* (volatile GLuint *)(imesa->MMIO_BASE+0x48c00))
452 #define MAXFIFO_S4 0x7F00
453 #define MAXFIFO_S3D 0x7F00
455 static GLboolean
savagePagePending_s4( savageContextPtr imesa
) {
456 return (ALT_STATUS_WORD0
& 0x08000000) ? GL_TRUE
: GL_FALSE
;
458 static GLboolean
savagePagePending_s3d( savageContextPtr imesa
) {
461 static void savageWaitForFIFO_s4( savageContextPtr imesa
, unsigned count
) {
463 int slots
= MAXFIFO_S4
-count
;
464 while((ALT_STATUS_WORD0
& 0x001fffff) > slots
&& loop
++ < MAXLOOP
);
466 static void savageWaitForFIFO_s3d( savageContextPtr imesa
, unsigned count
) {
468 int slots
= MAXFIFO_S3D
-count
;
469 while((STATUS_WORD0
& 0x0001ffff) > slots
&& loop
++ < MAXLOOP
);
471 static void savageWaitIdleEmpty_s4( savageContextPtr imesa
) {
473 while((ALT_STATUS_WORD0
& 0x00ffffff) != 0x00E00000L
&& loop
++ < MAXLOOP
);
475 static void savageWaitIdleEmpty_s3d( savageContextPtr imesa
) {
477 while((STATUS_WORD0
& 0x000fffff) != 0x000E0000L
&& loop
++ < MAXLOOP
);
480 GLboolean (*savagePagePending
)( savageContextPtr imesa
) = NULL
;
481 void (*savageWaitForFIFO
)( savageContextPtr imesa
, unsigned count
) = NULL
;
482 void (*savageWaitIdleEmpty
)( savageContextPtr imesa
) = NULL
;
485 void savageDDInitIoctlFuncs( GLcontext
*ctx
)
487 ctx
->Driver
.Clear
= savageDDClear
;
488 ctx
->Driver
.Flush
= savageDDFlush
;
489 ctx
->Driver
.Finish
= savageDDFinish
;
490 if (SAVAGE_CONTEXT( ctx
)->savageScreen
->chipset
>= S3_SAVAGE4
) {
491 savagePagePending
= savagePagePending_s4
;
492 savageWaitForFIFO
= savageWaitForFIFO_s4
;
493 savageWaitIdleEmpty
= savageWaitIdleEmpty_s4
;
495 savagePagePending
= savagePagePending_s3d
;
496 savageWaitForFIFO
= savageWaitForFIFO_s3d
;
497 savageWaitIdleEmpty
= savageWaitIdleEmpty_s3d
;
502 /* Alloc a continuous memory */
503 /* return: 0 error when kernel alloc pages(can try a half memory size)
506 int savageAllocDMABuffer(savageContextPtr imesa
, drm_savage_alloc_cont_mem_t
*req
)
512 if ((ret
=ioctl(imesa
->driFd
, DRM_IOCTL_SAVAGE_ALLOC_CONTINUOUS_MEM
, req
)) <=0)
519 /* get the physics address*/
520 GLuint
savageGetPhyAddress(savageContextPtr imesa
,void * pointer
)
523 drm_savage_get_physcis_address_t req
;
526 req
.v_address
= (GLuint
)pointer
;
527 ret
= ioctl(imesa
->driFd
, DRM_IOCTL_SAVAGE_GET_PHYSICS_ADDRESS
,&req
);
529 return req
.p_address
;
532 /* free the buffer got by savageAllocDMABuffe*/
533 int savageFreeDMABuffer(savageContextPtr imesa
, drm_savage_alloc_cont_mem_t
*req
)
539 if ((ret
=ioctl(imesa
->driFd
, DRM_IOCTL_SAVAGE_FREE_CONTINUOUS_MEM
, req
)) <=0)