Use SecondaryColorPtr, not ColorPtr[1] (the latter is NULL).
[mesa.git] / src / mesa / drivers / dri / trident / trident_state.c
1 /*
2 * Copyright 2002 by Alan Hourihane, Sychdyn, North Wales, UK.
3 *
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.
13 *
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.
21 *
22 * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk>
23 *
24 * Trident CyberBladeXP driver.
25 *
26 */
27 #include "trident_context.h"
28 #include "trident_lock.h"
29 #include "array_cache/acache.h"
30 #include "swrast/swrast.h"
31 #include "swrast_setup/swrast_setup.h"
32 #include "tnl/tnl.h"
33
34 #define TRIDENTPACKCOLOR332(r, g, b) \
35 (((r) & 0xe0) | (((g) & 0xe0) >> 3) | (((b) & 0xc0) >> 6))
36
37 #define TRIDENTPACKCOLOR1555(r, g, b, a) \
38 ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
39 ((a) ? 0x8000 : 0))
40
41 #define TRIDENTPACKCOLOR565(r, g, b) \
42 ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
43
44 #define TRIDENTPACKCOLOR888(r, g, b) \
45 (((r) << 16) | ((g) << 8) | (b))
46
47 #define TRIDENTPACKCOLOR8888(r, g, b, a) \
48 (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
49
50 #define TRIDENTPACKCOLOR4444(r, g, b, a) \
51 ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
52
53 static __inline__ GLuint tridentPackColor( GLuint cpp,
54 GLubyte r, GLubyte g,
55 GLubyte b, GLubyte a )
56 {
57 switch ( cpp ) {
58 case 2:
59 return TRIDENTPACKCOLOR565( r, g, b );
60 case 4:
61 return TRIDENTPACKCOLOR8888( r, g, b, a );
62 default:
63 return 0;
64 }
65 }
66
67 void tridentUploadHwStateLocked( tridentContextPtr tmesa )
68 {
69 unsigned char *MMIO = tmesa->tridentScreen->mmio.map;
70 #if 0
71 ATISAREAPrivPtr sarea = tmesa->sarea;
72 trident_context_regs_t *regs = &(sarea->ContextState);
73 #endif
74
75 if ( tmesa->dirty & TRIDENT_UPLOAD_COMMAND_D ) {
76 MMIO_OUT32(MMIO, 0x00281C, tmesa->commandD );
77 tmesa->dirty &= ~TRIDENT_UPLOAD_COMMAND_D;
78 }
79
80 if ( tmesa->dirty & TRIDENT_UPLOAD_CLIPRECTS ) {
81 /* XXX FIX ME ! */
82 MMIO_OUT32(MMIO, 0x002C80 , 0x20008000 | tmesa->tridentScreen->height );
83 MMIO_OUT32(MMIO, 0x002C84 , 0x20000000 | tmesa->tridentScreen->width );
84 tmesa->dirty &= ~TRIDENT_UPLOAD_CLIPRECTS;
85 }
86
87 tmesa->dirty = 0;
88 }
89
90 /* Copy the back color buffer to the front color buffer.
91 */
92 void tridentCopyBuffer( const __DRIdrawablePrivate *dPriv )
93 {
94 unsigned char *MMIO;
95 tridentContextPtr tmesa;
96 GLint nbox, i;
97 int busy;
98 drm_clip_rect_t *pbox;
99
100 assert(dPriv);
101 assert(dPriv->driContextPriv);
102 assert(dPriv->driContextPriv->driverPrivate);
103
104 tmesa = (tridentContextPtr) dPriv->driContextPriv->driverPrivate;
105 MMIO = tmesa->tridentScreen->mmio.map;
106
107 LOCK_HARDWARE( tmesa );
108
109 /* use front buffer cliprects */
110 nbox = dPriv->numClipRects;
111 pbox = dPriv->pClipRects;
112
113 for ( i = 0 ; i < nbox ; i++ ) {
114 #if 0
115 GLint nr = MIN2( i + MACH64_NR_SAREA_CLIPRECTS , nbox );
116 drm_clip_rect_t *b = tmesa->sarea->boxes;
117 GLint n = 0;
118
119 for ( ; i < nr ; i++ ) {
120 *b++ = pbox[i];
121 n++;
122 }
123 tmesa->sarea->nbox = n;
124 #endif
125
126 MMIO_OUT32(MMIO, 0x2150, tmesa->tridentScreen->frontPitch << 20 | tmesa->tridentScreen->frontOffset>>4);
127 MMIO_OUT32(MMIO, 0x2154, tmesa->tridentScreen->backPitch << 20 | tmesa->tridentScreen->backOffset>>4);
128 MMIO_OUT8(MMIO, 0x2127, 0xCC); /* Copy Rop */
129 MMIO_OUT32(MMIO, 0x2128, 0x4); /* scr2scr */
130 MMIO_OUT32(MMIO, 0x2138, (pbox->x1 << 16) | pbox->y1);
131 MMIO_OUT32(MMIO, 0x213C, (pbox->x1 << 16) | pbox->y1);
132 MMIO_OUT32(MMIO, 0x2140, (pbox->x2 - pbox->x1) << 16 | (pbox->y2 - pbox->y1) );
133 MMIO_OUT8(MMIO, 0x2124, 0x01); /* BLT */
134 #define GE_BUSY 0x80
135 for (;;) {
136 busy = MMIO_IN8(MMIO, 0x2120);
137 if ( !(busy & GE_BUSY) )
138 break;
139 }
140 }
141
142 UNLOCK_HARDWARE( tmesa );
143
144 #if 0
145 tmesa->dirty |= (MACH64_UPLOAD_CONTEXT |
146 MACH64_UPLOAD_MISC |
147 MACH64_UPLOAD_CLIPRECTS);
148 #endif
149 }
150
151
152 static void tridentDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
153 GLint cx, GLint cy, GLint cw, GLint ch )
154 {
155 tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx);
156 unsigned char *MMIO = tmesa->tridentScreen->mmio.map;
157 int busy;
158 GLuint flags = 0;
159 GLint i;
160
161 #define DRM_TRIDENT_FRONT 0x01
162 #define DRM_TRIDENT_BACK 0x02
163 #define DRM_TRIDENT_DEPTH 0x04
164
165 if ( tmesa->new_state )
166 tridentDDUpdateHWState( ctx );
167
168 if ( mask & DD_FRONT_LEFT_BIT ) {
169 flags |= DRM_TRIDENT_FRONT;
170 mask &= ~DD_FRONT_LEFT_BIT;
171 }
172
173 if ( mask & DD_BACK_LEFT_BIT ) {
174 flags |= DRM_TRIDENT_BACK;
175 mask &= ~DD_BACK_LEFT_BIT;
176 }
177
178 if ( ( mask & DD_DEPTH_BIT ) && ctx->Depth.Mask ) {
179 flags |= DRM_TRIDENT_DEPTH;
180 mask &= ~DD_DEPTH_BIT;
181 }
182
183 LOCK_HARDWARE(tmesa);
184
185 if ( flags ) {
186
187 cx += tmesa->drawX;
188 cy += tmesa->drawY;
189
190 /* HACK!!!
191 */
192 if ( tmesa->dirty & ~TRIDENT_UPLOAD_CLIPRECTS ) {
193 tridentUploadHwStateLocked( tmesa );
194 }
195
196 for ( i = 0 ; i < tmesa->numClipRects ; i++ ) {
197 #if 0
198 int nr = MIN2( i + TRIDENT_NR_SAREA_CLIPRECTS, tmesa->numClipRects );
199 drm_clip_rect_t *box = tmesa->pClipRects;
200 drm_clip_rect_t *b = tmesa->sarea->boxes;
201 GLint n = 0;
202
203 if ( !all ) {
204 for ( ; i < nr ; i++ ) {
205 GLint x = box[i].x1;
206 GLint y = box[i].y1;
207 GLint w = box[i].x2 - x;
208 GLint h = box[i].y2 - y;
209
210 if ( x < cx ) w -= cx - x, x = cx;
211 if ( y < cy ) h -= cy - y, y = cy;
212 if ( x + w > cx + cw ) w = cx + cw - x;
213 if ( y + h > cy + ch ) h = cy + ch - y;
214 if ( w <= 0 ) continue;
215 if ( h <= 0 ) continue;
216
217 b->x1 = x;
218 b->y1 = y;
219 b->x2 = x + w;
220 b->y2 = y + h;
221 b++;
222 n++;
223 }
224 } else {
225 for ( ; i < nr ; i++ ) {
226 *b++ = box[i];
227 n++;
228 }
229 }
230
231 tmesa->sarea->nbox = n;
232 #endif
233
234 if (flags & DRM_TRIDENT_BACK) {
235 MMIO_OUT32(MMIO, 0x2150, tmesa->tridentScreen->backPitch << 20 | tmesa->tridentScreen->backOffset>>4);
236 MMIO_OUT8(MMIO, 0x2127, 0xF0); /* Pat Rop */
237 MMIO_OUT32(MMIO, 0x2158, tmesa->ClearColor);
238 MMIO_OUT32(MMIO, 0x2128, 0x4000); /* solidfill */
239 MMIO_OUT32(MMIO, 0x2138, cx << 16 | cy);
240 MMIO_OUT32(MMIO, 0x2140, cw << 16 | ch);
241 MMIO_OUT8(MMIO, 0x2124, 0x01); /* BLT */
242 #define GE_BUSY 0x80
243 for (;;) {
244 busy = MMIO_IN8(MMIO, 0x2120);
245 if ( !(busy & GE_BUSY) )
246 break;
247 }
248 }
249 if (flags & DRM_TRIDENT_DEPTH) {
250 MMIO_OUT32(MMIO, 0x2150, tmesa->tridentScreen->depthPitch << 20 | tmesa->tridentScreen->depthOffset>>4);
251 MMIO_OUT8(MMIO, 0x2127, 0xF0); /* Pat Rop */
252 MMIO_OUT32(MMIO, 0x2158, tmesa->ClearColor);
253 MMIO_OUT32(MMIO, 0x2128, 0x4000); /* solidfill */
254 MMIO_OUT32(MMIO, 0x2138, cx << 16 | cy);
255 MMIO_OUT32(MMIO, 0x2140, cw << 16 | ch);
256 MMIO_OUT8(MMIO, 0x2124, 0x01); /* BLT */
257 #define GE_BUSY 0x80
258 for (;;) {
259 busy = MMIO_IN8(MMIO, 0x2120);
260 if ( !(busy & GE_BUSY) )
261 break;
262 }
263 }
264 MMIO_OUT32(MMIO, 0x2150, tmesa->tridentScreen->frontPitch << 20 | tmesa->tridentScreen->frontOffset>>4);
265 if (flags & DRM_TRIDENT_FRONT) {
266 MMIO_OUT8(MMIO, 0x2127, 0xF0); /* Pat Rop */
267 MMIO_OUT32(MMIO, 0x2158, tmesa->ClearColor);
268 MMIO_OUT32(MMIO, 0x2128, 0x4000); /* solidfill */
269 MMIO_OUT32(MMIO, 0x2138, cx << 16 | cy);
270 MMIO_OUT32(MMIO, 0x2140, cw << 16 | ch);
271 MMIO_OUT8(MMIO, 0x2124, 0x01); /* BLT */
272 #define GE_BUSY 0x80
273 for (;;) {
274 busy = MMIO_IN8(MMIO, 0x2120);
275 if ( !(busy & GE_BUSY) )
276 break;
277 }
278 }
279
280 }
281
282 #if 0
283 tmesa->dirty |= (TRIDENT_UPLOAD_CONTEXT |
284 TRIDENT_UPLOAD_MISC |
285 TRIDENT_UPLOAD_CLIPRECTS);
286 #endif
287 }
288
289 UNLOCK_HARDWARE(tmesa);
290
291 if ( mask )
292 _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
293 }
294
295 static void tridentDDShadeModel( GLcontext *ctx, GLenum mode )
296 {
297 tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx);
298 GLuint s = tmesa->commandD;
299
300 #define TRIDENT_FLAT_SHADE 0x000000E0
301 #define TRIDENT_FLAT_SHADE_VERTEX_C 0x00000060
302 #define TRIDENT_FLAT_SHADE_GOURAUD 0x00000080
303
304 s &= ~TRIDENT_FLAT_SHADE;
305
306 switch ( mode ) {
307 case GL_FLAT:
308 s |= TRIDENT_FLAT_SHADE_VERTEX_C;
309 break;
310 case GL_SMOOTH:
311 s |= TRIDENT_FLAT_SHADE_GOURAUD;
312 break;
313 default:
314 return;
315 }
316
317 if ( tmesa->commandD != s ) {
318 tmesa->commandD = s;
319
320 tmesa->dirty |= TRIDENT_UPLOAD_COMMAND_D;
321 }
322 }
323
324 void tridentCalcViewport( GLcontext *ctx )
325 {
326 tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx);
327 const GLfloat *v = ctx->Viewport._WindowMap.m;
328 GLfloat *m = tmesa->hw_viewport;
329
330 /* See also trident_translate_vertex.
331 */
332 m[MAT_SX] = v[MAT_SX];
333 m[MAT_TX] = v[MAT_TX] + tmesa->drawX + SUBPIXEL_X;
334 m[MAT_SY] = - v[MAT_SY];
335 m[MAT_TY] = - v[MAT_TY] + tmesa->driDrawable->h + tmesa->drawY + SUBPIXEL_Y;
336 #if 0
337 m[MAT_SZ] = v[MAT_SZ] * tmesa->depth_scale;
338 m[MAT_TZ] = v[MAT_TZ] * tmesa->depth_scale;
339 #else
340 m[MAT_SZ] = v[MAT_SZ];
341 m[MAT_TZ] = v[MAT_TZ];
342 #endif
343
344 tmesa->SetupNewInputs = ~0;
345 }
346
347 static void tridentDDViewport( GLcontext *ctx,
348 GLint x, GLint y,
349 GLsizei width, GLsizei height )
350 {
351 tridentCalcViewport( ctx );
352 }
353
354 static void tridentDDDepthRange( GLcontext *ctx,
355 GLclampd nearval, GLclampd farval )
356 {
357 tridentCalcViewport( ctx );
358 }
359
360 void tridentSetCliprects( tridentContextPtr tmesa, GLenum mode )
361 {
362 __DRIdrawablePrivate *dPriv = tmesa->driDrawable;
363
364 switch ( mode ) {
365 case GL_FRONT_LEFT:
366 if (dPriv->numClipRects == 0) {
367 static drm_clip_rect_t zeroareacliprect = {0,0,0,0};
368 tmesa->numClipRects = 1;
369 tmesa->pClipRects = &zeroareacliprect;
370 } else {
371 tmesa->numClipRects = dPriv->numClipRects;
372 tmesa->pClipRects = (drm_clip_rect_t *)dPriv->pClipRects;
373 }
374 tmesa->drawX = dPriv->x;
375 tmesa->drawY = dPriv->y;
376 break;
377 case GL_BACK_LEFT:
378 if ( dPriv->numBackClipRects == 0 ) {
379 if (dPriv->numClipRects == 0) {
380 static drm_clip_rect_t zeroareacliprect = {0,0,0,0};
381 tmesa->numClipRects = 1;
382 tmesa->pClipRects = &zeroareacliprect;
383 } else {
384 tmesa->numClipRects = dPriv->numClipRects;
385 tmesa->pClipRects = (drm_clip_rect_t *)dPriv->pClipRects;
386 tmesa->drawX = dPriv->x;
387 tmesa->drawY = dPriv->y;
388 }
389 }
390 else {
391 tmesa->numClipRects = dPriv->numBackClipRects;
392 tmesa->pClipRects = (drm_clip_rect_t *)dPriv->pBackClipRects;
393 tmesa->drawX = dPriv->backX;
394 tmesa->drawY = dPriv->backY;
395 }
396 break;
397 default:
398 return;
399 }
400
401 #if 0
402 tmesa->dirty |= TRIDENT_UPLOAD_CLIPRECTS;
403 #endif
404 }
405
406 #if 0
407 static GLboolean tridentDDSetDrawBuffer( GLcontext *ctx, GLenum mode )
408 {
409 tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx);
410 int found = GL_TRUE;
411
412 if ( tmesa->DrawBuffer != mode ) {
413 tmesa->DrawBuffer = mode;
414
415 switch ( mode ) {
416 case GL_FRONT_LEFT:
417 tridentFallback( tmesa, TRIDENT_FALLBACK_DRAW_BUFFER, GL_FALSE );
418 tmesa->drawOffset = tmesa->tridentScreen->frontOffset;
419 tmesa->drawPitch = tmesa->tridentScreen->frontPitch;
420 tridentSetCliprects( tmesa, GL_FRONT_LEFT );
421 break;
422 case GL_BACK_LEFT:
423 tridentFallback( tmesa, TRIDENT_FALLBACK_DRAW_BUFFER, GL_FALSE );
424 tmesa->drawOffset = tmesa->tridentScreen->backOffset;
425 tmesa->drawPitch = tmesa->tridentScreen->backPitch;
426 tridentSetCliprects( tmesa, GL_BACK_LEFT );
427 break;
428 default:
429 tridentFallback( tmesa, TRIDENT_FALLBACK_DRAW_BUFFER, GL_TRUE );
430 found = GL_FALSE;
431 break;
432 }
433
434 #if 0
435 tmesa->setup.dst_off_pitch = (((tmesa->drawPitch/8) << 22) |
436 (tmesa->drawOffset >> 3));
437
438 tmesa->dirty |= MACH64_UPLOAD_DST_OFF_PITCH | MACH64_UPLOAD_CONTEXT;
439 #endif
440
441 }
442
443 return found;
444 }
445
446 static void tridentDDClearColor( GLcontext *ctx,
447 const GLchan color[4] )
448 {
449 tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx);
450
451 tmesa->ClearColor = tridentPackColor( tmesa->tridentScreen->cpp,
452 color[0], color[1],
453 color[2], color[3] );
454 }
455 #endif
456
457 void tridentDDUpdateState( GLcontext *ctx, GLuint new_state )
458 {
459 _swrast_InvalidateState( ctx, new_state );
460 _swsetup_InvalidateState( ctx, new_state );
461 _ac_InvalidateState( ctx, new_state );
462 _tnl_InvalidateState( ctx, new_state );
463 TRIDENT_CONTEXT(ctx)->new_gl_state |= new_state;
464 }
465
466
467 /* Initialize the context's hardware state.
468 */
469 void tridentDDInitState( tridentContextPtr tmesa )
470 {
471 tmesa->new_state = 0;
472
473 switch ( tmesa->glCtx->Visual.depthBits ) {
474 case 16:
475 tmesa->depth_scale = 1.0 / (GLfloat)0xffff;
476 break;
477 case 24:
478 tmesa->depth_scale = 1.0 / (GLfloat)0xffffff;
479 break;
480 }
481 }
482
483 void tridentDDUpdateHWState( GLcontext *ctx )
484 {
485 tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx);
486 int new_state = tmesa->new_state;
487
488 if ( new_state )
489 {
490 tmesa->new_state = 0;
491
492 #if 0
493 /* Update the various parts of the context's state.
494 */
495 if ( new_state & GAMMA_NEW_ALPHA )
496 tridentUpdateAlphaMode( ctx );
497
498 if ( new_state & GAMMA_NEW_DEPTH )
499 tridentUpdateZMode( ctx );
500
501 if ( new_state & GAMMA_NEW_FOG )
502 gammaUpdateFogAttrib( ctx );
503
504 if ( new_state & GAMMA_NEW_CLIP )
505 gammaUpdateClipping( ctx );
506
507 if ( new_state & GAMMA_NEW_POLYGON )
508 gammaUpdatePolygon( ctx );
509
510 if ( new_state & GAMMA_NEW_CULL )
511 gammaUpdateCull( ctx );
512
513 if ( new_state & GAMMA_NEW_MASKS )
514 gammaUpdateMasks( ctx );
515
516 if ( new_state & GAMMA_NEW_STIPPLE )
517 gammaUpdateStipple( ctx );
518 #endif
519 }
520
521 /* HACK ! */
522
523 #if 0
524 gammaEmitHwState( tmesa );
525 #endif
526 }
527
528 /* Initialize the driver's state functions.
529 */
530 void tridentDDInitStateFuncs( GLcontext *ctx )
531 {
532 ctx->Driver.UpdateState = tridentDDUpdateState;
533
534 ctx->Driver.Clear = tridentDDClear;
535 ctx->Driver.DepthRange = tridentDDDepthRange;
536 ctx->Driver.ShadeModel = tridentDDShadeModel;
537 ctx->Driver.Viewport = tridentDDViewport;
538
539 /* Pixel path fallbacks.
540 */
541 ctx->Driver.Accum = _swrast_Accum;
542 ctx->Driver.Bitmap = _swrast_Bitmap;
543 ctx->Driver.CopyPixels = _swrast_CopyPixels;
544 ctx->Driver.DrawPixels = _swrast_DrawPixels;
545 ctx->Driver.ReadPixels = _swrast_ReadPixels;
546 ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
547
548 /* Swrast hooks for imaging extensions:
549 */
550 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
551 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
552 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
553 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
554 }