2 * Copyright 2002 by Alan Hourihane, Sychdyn, North Wales, UK.
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Alan Hourihane not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Alan Hourihane makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
22 * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk>
24 * Trident CyberBladeXP driver.
27 #include "trident_context.h"
28 #include "trident_lock.h"
30 #include "swrast/swrast.h"
31 #include "swrast_setup/swrast_setup.h"
33 #include "main/framebuffer.h"
35 #define TRIDENTPACKCOLOR332(r, g, b) \
36 (((r) & 0xe0) | (((g) & 0xe0) >> 3) | (((b) & 0xc0) >> 6))
38 #define TRIDENTPACKCOLOR1555(r, g, b, a) \
39 ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
42 #define TRIDENTPACKCOLOR565(r, g, b) \
43 ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
45 #define TRIDENTPACKCOLOR888(r, g, b) \
46 (((r) << 16) | ((g) << 8) | (b))
48 #define TRIDENTPACKCOLOR8888(r, g, b, a) \
49 (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
51 #define TRIDENTPACKCOLOR4444(r, g, b, a) \
52 ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
54 static INLINE GLuint
tridentPackColor( GLuint cpp
,
56 GLubyte b
, GLubyte a
)
60 return TRIDENTPACKCOLOR565( r
, g
, b
);
62 return TRIDENTPACKCOLOR8888( r
, g
, b
, a
);
68 void tridentUploadHwStateLocked( tridentContextPtr tmesa
)
70 unsigned char *MMIO
= tmesa
->tridentScreen
->mmio
.map
;
72 ATISAREAPrivPtr sarea
= tmesa
->sarea
;
73 trident_context_regs_t
*regs
= &(sarea
->ContextState
);
76 if ( tmesa
->dirty
& TRIDENT_UPLOAD_COMMAND_D
) {
77 MMIO_OUT32(MMIO
, 0x00281C, tmesa
->commandD
);
78 tmesa
->dirty
&= ~TRIDENT_UPLOAD_COMMAND_D
;
81 if ( tmesa
->dirty
& TRIDENT_UPLOAD_CLIPRECTS
) {
83 MMIO_OUT32(MMIO
, 0x002C80 , 0x20008000 | tmesa
->tridentScreen
->height
);
84 MMIO_OUT32(MMIO
, 0x002C84 , 0x20000000 | tmesa
->tridentScreen
->width
);
85 tmesa
->dirty
&= ~TRIDENT_UPLOAD_CLIPRECTS
;
91 /* Copy the back color buffer to the front color buffer.
93 void tridentCopyBuffer( const __DRIdrawablePrivate
*dPriv
)
96 tridentContextPtr tmesa
;
99 drm_clip_rect_t
*pbox
;
102 assert(dPriv
->driContextPriv
);
103 assert(dPriv
->driContextPriv
->driverPrivate
);
105 tmesa
= (tridentContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
106 MMIO
= tmesa
->tridentScreen
->mmio
.map
;
108 LOCK_HARDWARE( tmesa
);
110 /* use front buffer cliprects */
111 nbox
= dPriv
->numClipRects
;
112 pbox
= dPriv
->pClipRects
;
114 for ( i
= 0 ; i
< nbox
; i
++ ) {
116 GLint nr
= MIN2( i
+ MACH64_NR_SAREA_CLIPRECTS
, nbox
);
117 drm_clip_rect_t
*b
= tmesa
->sarea
->boxes
;
120 for ( ; i
< nr
; i
++ ) {
124 tmesa
->sarea
->nbox
= n
;
127 MMIO_OUT32(MMIO
, 0x2150, tmesa
->tridentScreen
->frontPitch
<< 20 | tmesa
->tridentScreen
->frontOffset
>>4);
128 MMIO_OUT32(MMIO
, 0x2154, tmesa
->tridentScreen
->backPitch
<< 20 | tmesa
->tridentScreen
->backOffset
>>4);
129 MMIO_OUT8(MMIO
, 0x2127, 0xCC); /* Copy Rop */
130 MMIO_OUT32(MMIO
, 0x2128, 0x4); /* scr2scr */
131 MMIO_OUT32(MMIO
, 0x2138, (pbox
->x1
<< 16) | pbox
->y1
);
132 MMIO_OUT32(MMIO
, 0x213C, (pbox
->x1
<< 16) | pbox
->y1
);
133 MMIO_OUT32(MMIO
, 0x2140, (pbox
->x2
- pbox
->x1
) << 16 | (pbox
->y2
- pbox
->y1
) );
134 MMIO_OUT8(MMIO
, 0x2124, 0x01); /* BLT */
137 busy
= MMIO_IN8(MMIO
, 0x2120);
138 if ( !(busy
& GE_BUSY
) )
143 UNLOCK_HARDWARE( tmesa
);
146 tmesa
->dirty
|= (MACH64_UPLOAD_CONTEXT
|
148 MACH64_UPLOAD_CLIPRECTS
);
153 static void tridentDDClear( GLcontext
*ctx
, GLbitfield mask
)
155 tridentContextPtr tmesa
= TRIDENT_CONTEXT(ctx
);
156 unsigned char *MMIO
= tmesa
->tridentScreen
->mmio
.map
;
160 GLint cx
, cy
, cw
, ch
;
162 #define DRM_TRIDENT_FRONT 0x01
163 #define DRM_TRIDENT_BACK 0x02
164 #define DRM_TRIDENT_DEPTH 0x04
166 if ( tmesa
->new_state
)
167 tridentDDUpdateHWState( ctx
);
169 if ( mask
& BUFFER_BIT_FRONT_LEFT
) {
170 flags
|= DRM_TRIDENT_FRONT
;
171 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
174 if ( mask
& BUFFER_BIT_BACK_LEFT
) {
175 flags
|= DRM_TRIDENT_BACK
;
176 mask
&= ~BUFFER_BIT_BACK_LEFT
;
179 if ( ( mask
& BUFFER_BIT_DEPTH
) && ctx
->Depth
.Mask
) {
180 flags
|= DRM_TRIDENT_DEPTH
;
181 mask
&= ~BUFFER_BIT_DEPTH
;
184 LOCK_HARDWARE(tmesa
);
186 /* get region after locking: */
187 cx
= ctx
->DrawBuffer
->_Xmin
;
188 cy
= ctx
->DrawBuffer
->_Ymin
;
189 cw
= ctx
->DrawBuffer
->_Xmax
- cx
;
190 ch
= ctx
->DrawBuffer
->_Ymax
- cy
;
199 if ( tmesa
->dirty
& ~TRIDENT_UPLOAD_CLIPRECTS
) {
200 tridentUploadHwStateLocked( tmesa
);
203 for ( i
= 0 ; i
< tmesa
->numClipRects
; i
++ ) {
205 int nr
= MIN2( i
+ TRIDENT_NR_SAREA_CLIPRECTS
, tmesa
->numClipRects
);
206 drm_clip_rect_t
*box
= tmesa
->pClipRects
;
207 drm_clip_rect_t
*b
= tmesa
->sarea
->boxes
;
211 for ( ; i
< nr
; i
++ ) {
214 GLint w
= box
[i
].x2
- x
;
215 GLint h
= box
[i
].y2
- y
;
217 if ( x
< cx
) w
-= cx
- x
, x
= cx
;
218 if ( y
< cy
) h
-= cy
- y
, y
= cy
;
219 if ( x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
220 if ( y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
221 if ( w
<= 0 ) continue;
222 if ( h
<= 0 ) continue;
232 for ( ; i
< nr
; i
++ ) {
238 tmesa
->sarea
->nbox
= n
;
241 if (flags
& DRM_TRIDENT_BACK
) {
242 MMIO_OUT32(MMIO
, 0x2150, tmesa
->tridentScreen
->backPitch
<< 20 | tmesa
->tridentScreen
->backOffset
>>4);
243 MMIO_OUT8(MMIO
, 0x2127, 0xF0); /* Pat Rop */
244 MMIO_OUT32(MMIO
, 0x2158, tmesa
->ClearColor
);
245 MMIO_OUT32(MMIO
, 0x2128, 0x4000); /* solidfill */
246 MMIO_OUT32(MMIO
, 0x2138, cx
<< 16 | cy
);
247 MMIO_OUT32(MMIO
, 0x2140, cw
<< 16 | ch
);
248 MMIO_OUT8(MMIO
, 0x2124, 0x01); /* BLT */
251 busy
= MMIO_IN8(MMIO
, 0x2120);
252 if ( !(busy
& GE_BUSY
) )
256 if (flags
& DRM_TRIDENT_DEPTH
) {
257 MMIO_OUT32(MMIO
, 0x2150, tmesa
->tridentScreen
->depthPitch
<< 20 | tmesa
->tridentScreen
->depthOffset
>>4);
258 MMIO_OUT8(MMIO
, 0x2127, 0xF0); /* Pat Rop */
259 MMIO_OUT32(MMIO
, 0x2158, tmesa
->ClearColor
);
260 MMIO_OUT32(MMIO
, 0x2128, 0x4000); /* solidfill */
261 MMIO_OUT32(MMIO
, 0x2138, cx
<< 16 | cy
);
262 MMIO_OUT32(MMIO
, 0x2140, cw
<< 16 | ch
);
263 MMIO_OUT8(MMIO
, 0x2124, 0x01); /* BLT */
266 busy
= MMIO_IN8(MMIO
, 0x2120);
267 if ( !(busy
& GE_BUSY
) )
271 MMIO_OUT32(MMIO
, 0x2150, tmesa
->tridentScreen
->frontPitch
<< 20 | tmesa
->tridentScreen
->frontOffset
>>4);
272 if (flags
& DRM_TRIDENT_FRONT
) {
273 MMIO_OUT8(MMIO
, 0x2127, 0xF0); /* Pat Rop */
274 MMIO_OUT32(MMIO
, 0x2158, tmesa
->ClearColor
);
275 MMIO_OUT32(MMIO
, 0x2128, 0x4000); /* solidfill */
276 MMIO_OUT32(MMIO
, 0x2138, cx
<< 16 | cy
);
277 MMIO_OUT32(MMIO
, 0x2140, cw
<< 16 | ch
);
278 MMIO_OUT8(MMIO
, 0x2124, 0x01); /* BLT */
281 busy
= MMIO_IN8(MMIO
, 0x2120);
282 if ( !(busy
& GE_BUSY
) )
290 tmesa
->dirty
|= (TRIDENT_UPLOAD_CONTEXT
|
291 TRIDENT_UPLOAD_MISC
|
292 TRIDENT_UPLOAD_CLIPRECTS
);
296 UNLOCK_HARDWARE(tmesa
);
299 _swrast_Clear( ctx
, mask
);
302 static void tridentDDShadeModel( GLcontext
*ctx
, GLenum mode
)
304 tridentContextPtr tmesa
= TRIDENT_CONTEXT(ctx
);
305 GLuint s
= tmesa
->commandD
;
307 #define TRIDENT_FLAT_SHADE 0x000000E0
308 #define TRIDENT_FLAT_SHADE_VERTEX_C 0x00000060
309 #define TRIDENT_FLAT_SHADE_GOURAUD 0x00000080
311 s
&= ~TRIDENT_FLAT_SHADE
;
315 s
|= TRIDENT_FLAT_SHADE_VERTEX_C
;
318 s
|= TRIDENT_FLAT_SHADE_GOURAUD
;
324 if ( tmesa
->commandD
!= s
) {
327 tmesa
->dirty
|= TRIDENT_UPLOAD_COMMAND_D
;
332 tridentCalcViewport( GLcontext
*ctx
)
334 tridentContextPtr tmesa
= TRIDENT_CONTEXT(ctx
);
335 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
336 GLfloat
*m
= tmesa
->hw_viewport
;
338 /* See also trident_translate_vertex.
340 m
[MAT_SX
] = v
[MAT_SX
];
341 m
[MAT_TX
] = v
[MAT_TX
] + tmesa
->drawX
+ SUBPIXEL_X
;
342 m
[MAT_SY
] = - v
[MAT_SY
];
343 m
[MAT_TY
] = - v
[MAT_TY
] + tmesa
->driDrawable
->h
+ tmesa
->drawY
+ SUBPIXEL_Y
;
345 m
[MAT_SZ
] = v
[MAT_SZ
] * tmesa
->depth_scale
;
346 m
[MAT_TZ
] = v
[MAT_TZ
] * tmesa
->depth_scale
;
348 m
[MAT_SZ
] = v
[MAT_SZ
];
349 m
[MAT_TZ
] = v
[MAT_TZ
];
352 tmesa
->SetupNewInputs
= ~0;
355 static void tridentDDViewport( GLcontext
*ctx
,
357 GLsizei width
, GLsizei height
)
359 tridentCalcViewport( ctx
);
362 static void tridentDDDepthRange( GLcontext
*ctx
,
363 GLclampd nearval
, GLclampd farval
)
365 tridentCalcViewport( ctx
);
369 tridentSetCliprects( tridentContextPtr tmesa
, GLenum mode
)
371 __DRIdrawablePrivate
*dPriv
= tmesa
->driDrawable
;
375 if (dPriv
->numClipRects
== 0) {
376 static drm_clip_rect_t zeroareacliprect
= {0,0,0,0};
377 tmesa
->numClipRects
= 1;
378 tmesa
->pClipRects
= &zeroareacliprect
;
380 tmesa
->numClipRects
= dPriv
->numClipRects
;
381 tmesa
->pClipRects
= (drm_clip_rect_t
*)dPriv
->pClipRects
;
383 tmesa
->drawX
= dPriv
->x
;
384 tmesa
->drawY
= dPriv
->y
;
387 if ( dPriv
->numBackClipRects
== 0 ) {
388 if (dPriv
->numClipRects
== 0) {
389 static drm_clip_rect_t zeroareacliprect
= {0,0,0,0};
390 tmesa
->numClipRects
= 1;
391 tmesa
->pClipRects
= &zeroareacliprect
;
393 tmesa
->numClipRects
= dPriv
->numClipRects
;
394 tmesa
->pClipRects
= (drm_clip_rect_t
*)dPriv
->pClipRects
;
395 tmesa
->drawX
= dPriv
->x
;
396 tmesa
->drawY
= dPriv
->y
;
400 tmesa
->numClipRects
= dPriv
->numBackClipRects
;
401 tmesa
->pClipRects
= (drm_clip_rect_t
*)dPriv
->pBackClipRects
;
402 tmesa
->drawX
= dPriv
->backX
;
403 tmesa
->drawY
= dPriv
->backY
;
411 tmesa
->dirty
|= TRIDENT_UPLOAD_CLIPRECTS
;
416 static GLboolean
tridentDDSetDrawBuffer( GLcontext
*ctx
, GLenum mode
)
418 tridentContextPtr tmesa
= TRIDENT_CONTEXT(ctx
);
421 if ( tmesa
->DrawBuffer
!= mode
) {
422 tmesa
->DrawBuffer
= mode
;
426 tridentFallback( tmesa
, TRIDENT_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
427 tmesa
->drawOffset
= tmesa
->tridentScreen
->frontOffset
;
428 tmesa
->drawPitch
= tmesa
->tridentScreen
->frontPitch
;
429 tridentSetCliprects( tmesa
, GL_FRONT_LEFT
);
432 tridentFallback( tmesa
, TRIDENT_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
433 tmesa
->drawOffset
= tmesa
->tridentScreen
->backOffset
;
434 tmesa
->drawPitch
= tmesa
->tridentScreen
->backPitch
;
435 tridentSetCliprects( tmesa
, GL_BACK_LEFT
);
438 tridentFallback( tmesa
, TRIDENT_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
444 tmesa
->setup
.dst_off_pitch
= (((tmesa
->drawPitch
/8) << 22) |
445 (tmesa
->drawOffset
>> 3));
447 tmesa
->dirty
|= MACH64_UPLOAD_DST_OFF_PITCH
| MACH64_UPLOAD_CONTEXT
;
455 static void tridentDDClearColor( GLcontext
*ctx
,
456 const GLchan color
[4] )
458 tridentContextPtr tmesa
= TRIDENT_CONTEXT(ctx
);
460 tmesa
->ClearColor
= tridentPackColor( tmesa
->tridentScreen
->cpp
,
462 color
[2], color
[3] );
467 tridentDDUpdateState( GLcontext
*ctx
, GLuint new_state
)
469 _swrast_InvalidateState( ctx
, new_state
);
470 _swsetup_InvalidateState( ctx
, new_state
);
471 _vbo_InvalidateState( ctx
, new_state
);
472 _tnl_InvalidateState( ctx
, new_state
);
473 TRIDENT_CONTEXT(ctx
)->new_gl_state
|= new_state
;
477 /* Initialize the context's hardware state.
479 void tridentDDInitState( tridentContextPtr tmesa
)
481 tmesa
->new_state
= 0;
483 switch ( tmesa
->glCtx
->Visual
.depthBits
) {
485 tmesa
->depth_scale
= 1.0 / (GLfloat
)0xffff;
488 tmesa
->depth_scale
= 1.0 / (GLfloat
)0xffffff;
493 void tridentDDUpdateHWState( GLcontext
*ctx
)
495 tridentContextPtr tmesa
= TRIDENT_CONTEXT(ctx
);
496 int new_state
= tmesa
->new_state
;
500 tmesa
->new_state
= 0;
503 /* Update the various parts of the context's state.
505 if ( new_state
& GAMMA_NEW_ALPHA
)
506 tridentUpdateAlphaMode( ctx
);
508 if ( new_state
& GAMMA_NEW_DEPTH
)
509 tridentUpdateZMode( ctx
);
511 if ( new_state
& GAMMA_NEW_FOG
)
512 gammaUpdateFogAttrib( ctx
);
514 if ( new_state
& GAMMA_NEW_CLIP
)
515 gammaUpdateClipping( ctx
);
517 if ( new_state
& GAMMA_NEW_POLYGON
)
518 gammaUpdatePolygon( ctx
);
520 if ( new_state
& GAMMA_NEW_CULL
)
521 gammaUpdateCull( ctx
);
523 if ( new_state
& GAMMA_NEW_MASKS
)
524 gammaUpdateMasks( ctx
);
526 if ( new_state
& GAMMA_NEW_STIPPLE
)
527 gammaUpdateStipple( ctx
);
534 gammaEmitHwState( tmesa
);
538 /* Initialize the driver's state functions.
540 void tridentDDInitStateFuncs( GLcontext
*ctx
)
542 ctx
->Driver
.UpdateState
= tridentDDUpdateState
;
544 ctx
->Driver
.Clear
= tridentDDClear
;
545 ctx
->Driver
.DepthRange
= tridentDDDepthRange
;
546 ctx
->Driver
.ShadeModel
= tridentDDShadeModel
;
547 ctx
->Driver
.Viewport
= tridentDDViewport
;