r300_fragprog: Use nqssa+dce and program_pair for emit
[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 "vbo/vbo.h"
30 #include "swrast/swrast.h"
31 #include "swrast_setup/swrast_setup.h"
32 #include "tnl/tnl.h"
33 #include "framebuffer.h"
34
35 #define TRIDENTPACKCOLOR332(r, g, b) \
36 (((r) & 0xe0) | (((g) & 0xe0) >> 3) | (((b) & 0xc0) >> 6))
37
38 #define TRIDENTPACKCOLOR1555(r, g, b, a) \
39 ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
40 ((a) ? 0x8000 : 0))
41
42 #define TRIDENTPACKCOLOR565(r, g, b) \
43 ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
44
45 #define TRIDENTPACKCOLOR888(r, g, b) \
46 (((r) << 16) | ((g) << 8) | (b))
47
48 #define TRIDENTPACKCOLOR8888(r, g, b, a) \
49 (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
50
51 #define TRIDENTPACKCOLOR4444(r, g, b, a) \
52 ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
53
54 static INLINE GLuint tridentPackColor( GLuint cpp,
55 GLubyte r, GLubyte g,
56 GLubyte b, GLubyte a )
57 {
58 switch ( cpp ) {
59 case 2:
60 return TRIDENTPACKCOLOR565( r, g, b );
61 case 4:
62 return TRIDENTPACKCOLOR8888( r, g, b, a );
63 default:
64 return 0;
65 }
66 }
67
68 void tridentUploadHwStateLocked( tridentContextPtr tmesa )
69 {
70 unsigned char *MMIO = tmesa->tridentScreen->mmio.map;
71 #if 0
72 ATISAREAPrivPtr sarea = tmesa->sarea;
73 trident_context_regs_t *regs = &(sarea->ContextState);
74 #endif
75
76 if ( tmesa->dirty & TRIDENT_UPLOAD_COMMAND_D ) {
77 MMIO_OUT32(MMIO, 0x00281C, tmesa->commandD );
78 tmesa->dirty &= ~TRIDENT_UPLOAD_COMMAND_D;
79 }
80
81 if ( tmesa->dirty & TRIDENT_UPLOAD_CLIPRECTS ) {
82 /* XXX FIX ME ! */
83 MMIO_OUT32(MMIO, 0x002C80 , 0x20008000 | tmesa->tridentScreen->height );
84 MMIO_OUT32(MMIO, 0x002C84 , 0x20000000 | tmesa->tridentScreen->width );
85 tmesa->dirty &= ~TRIDENT_UPLOAD_CLIPRECTS;
86 }
87
88 tmesa->dirty = 0;
89 }
90
91 /* Copy the back color buffer to the front color buffer.
92 */
93 void tridentCopyBuffer( const __DRIdrawablePrivate *dPriv )
94 {
95 unsigned char *MMIO;
96 tridentContextPtr tmesa;
97 GLint nbox, i;
98 int busy;
99 drm_clip_rect_t *pbox;
100
101 assert(dPriv);
102 assert(dPriv->driContextPriv);
103 assert(dPriv->driContextPriv->driverPrivate);
104
105 tmesa = (tridentContextPtr) dPriv->driContextPriv->driverPrivate;
106 MMIO = tmesa->tridentScreen->mmio.map;
107
108 LOCK_HARDWARE( tmesa );
109
110 /* use front buffer cliprects */
111 nbox = dPriv->numClipRects;
112 pbox = dPriv->pClipRects;
113
114 for ( i = 0 ; i < nbox ; i++ ) {
115 #if 0
116 GLint nr = MIN2( i + MACH64_NR_SAREA_CLIPRECTS , nbox );
117 drm_clip_rect_t *b = tmesa->sarea->boxes;
118 GLint n = 0;
119
120 for ( ; i < nr ; i++ ) {
121 *b++ = pbox[i];
122 n++;
123 }
124 tmesa->sarea->nbox = n;
125 #endif
126
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 */
135 #define GE_BUSY 0x80
136 for (;;) {
137 busy = MMIO_IN8(MMIO, 0x2120);
138 if ( !(busy & GE_BUSY) )
139 break;
140 }
141 }
142
143 UNLOCK_HARDWARE( tmesa );
144
145 #if 0
146 tmesa->dirty |= (MACH64_UPLOAD_CONTEXT |
147 MACH64_UPLOAD_MISC |
148 MACH64_UPLOAD_CLIPRECTS);
149 #endif
150 }
151
152
153 static void tridentDDClear( GLcontext *ctx, GLbitfield mask )
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 GLint cx, cy, cw, ch;
161
162 #define DRM_TRIDENT_FRONT 0x01
163 #define DRM_TRIDENT_BACK 0x02
164 #define DRM_TRIDENT_DEPTH 0x04
165
166 if ( tmesa->new_state )
167 tridentDDUpdateHWState( ctx );
168
169 if ( mask & BUFFER_BIT_FRONT_LEFT ) {
170 flags |= DRM_TRIDENT_FRONT;
171 mask &= ~BUFFER_BIT_FRONT_LEFT;
172 }
173
174 if ( mask & BUFFER_BIT_BACK_LEFT ) {
175 flags |= DRM_TRIDENT_BACK;
176 mask &= ~BUFFER_BIT_BACK_LEFT;
177 }
178
179 if ( ( mask & BUFFER_BIT_DEPTH ) && ctx->Depth.Mask ) {
180 flags |= DRM_TRIDENT_DEPTH;
181 mask &= ~BUFFER_BIT_DEPTH;
182 }
183
184 LOCK_HARDWARE(tmesa);
185
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;
191
192 if ( flags ) {
193
194 cx += tmesa->drawX;
195 cy += tmesa->drawY;
196
197 /* HACK!!!
198 */
199 if ( tmesa->dirty & ~TRIDENT_UPLOAD_CLIPRECTS ) {
200 tridentUploadHwStateLocked( tmesa );
201 }
202
203 for ( i = 0 ; i < tmesa->numClipRects ; i++ ) {
204 #if 0
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;
208 GLint n = 0;
209
210 if ( !all ) {
211 for ( ; i < nr ; i++ ) {
212 GLint x = box[i].x1;
213 GLint y = box[i].y1;
214 GLint w = box[i].x2 - x;
215 GLint h = box[i].y2 - y;
216
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;
223
224 b->x1 = x;
225 b->y1 = y;
226 b->x2 = x + w;
227 b->y2 = y + h;
228 b++;
229 n++;
230 }
231 } else {
232 for ( ; i < nr ; i++ ) {
233 *b++ = box[i];
234 n++;
235 }
236 }
237
238 tmesa->sarea->nbox = n;
239 #endif
240
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 */
249 #define GE_BUSY 0x80
250 for (;;) {
251 busy = MMIO_IN8(MMIO, 0x2120);
252 if ( !(busy & GE_BUSY) )
253 break;
254 }
255 }
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 */
264 #define GE_BUSY 0x80
265 for (;;) {
266 busy = MMIO_IN8(MMIO, 0x2120);
267 if ( !(busy & GE_BUSY) )
268 break;
269 }
270 }
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 */
279 #define GE_BUSY 0x80
280 for (;;) {
281 busy = MMIO_IN8(MMIO, 0x2120);
282 if ( !(busy & GE_BUSY) )
283 break;
284 }
285 }
286
287 }
288
289 #if 0
290 tmesa->dirty |= (TRIDENT_UPLOAD_CONTEXT |
291 TRIDENT_UPLOAD_MISC |
292 TRIDENT_UPLOAD_CLIPRECTS);
293 #endif
294 }
295
296 UNLOCK_HARDWARE(tmesa);
297
298 if ( mask )
299 _swrast_Clear( ctx, mask );
300 }
301
302 static void tridentDDShadeModel( GLcontext *ctx, GLenum mode )
303 {
304 tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx);
305 GLuint s = tmesa->commandD;
306
307 #define TRIDENT_FLAT_SHADE 0x000000E0
308 #define TRIDENT_FLAT_SHADE_VERTEX_C 0x00000060
309 #define TRIDENT_FLAT_SHADE_GOURAUD 0x00000080
310
311 s &= ~TRIDENT_FLAT_SHADE;
312
313 switch ( mode ) {
314 case GL_FLAT:
315 s |= TRIDENT_FLAT_SHADE_VERTEX_C;
316 break;
317 case GL_SMOOTH:
318 s |= TRIDENT_FLAT_SHADE_GOURAUD;
319 break;
320 default:
321 return;
322 }
323
324 if ( tmesa->commandD != s ) {
325 tmesa->commandD = s;
326
327 tmesa->dirty |= TRIDENT_UPLOAD_COMMAND_D;
328 }
329 }
330
331 static void
332 tridentCalcViewport( GLcontext *ctx )
333 {
334 tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx);
335 const GLfloat *v = ctx->Viewport._WindowMap.m;
336 GLfloat *m = tmesa->hw_viewport;
337
338 /* See also trident_translate_vertex.
339 */
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;
344 #if 0
345 m[MAT_SZ] = v[MAT_SZ] * tmesa->depth_scale;
346 m[MAT_TZ] = v[MAT_TZ] * tmesa->depth_scale;
347 #else
348 m[MAT_SZ] = v[MAT_SZ];
349 m[MAT_TZ] = v[MAT_TZ];
350 #endif
351
352 tmesa->SetupNewInputs = ~0;
353 }
354
355 static void tridentDDViewport( GLcontext *ctx,
356 GLint x, GLint y,
357 GLsizei width, GLsizei height )
358 {
359 tridentCalcViewport( ctx );
360 }
361
362 static void tridentDDDepthRange( GLcontext *ctx,
363 GLclampd nearval, GLclampd farval )
364 {
365 tridentCalcViewport( ctx );
366 }
367
368 static void
369 tridentSetCliprects( tridentContextPtr tmesa, GLenum mode )
370 {
371 __DRIdrawablePrivate *dPriv = tmesa->driDrawable;
372
373 switch ( mode ) {
374 case GL_FRONT_LEFT:
375 if (dPriv->numClipRects == 0) {
376 static drm_clip_rect_t zeroareacliprect = {0,0,0,0};
377 tmesa->numClipRects = 1;
378 tmesa->pClipRects = &zeroareacliprect;
379 } else {
380 tmesa->numClipRects = dPriv->numClipRects;
381 tmesa->pClipRects = (drm_clip_rect_t *)dPriv->pClipRects;
382 }
383 tmesa->drawX = dPriv->x;
384 tmesa->drawY = dPriv->y;
385 break;
386 case GL_BACK_LEFT:
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;
392 } else {
393 tmesa->numClipRects = dPriv->numClipRects;
394 tmesa->pClipRects = (drm_clip_rect_t *)dPriv->pClipRects;
395 tmesa->drawX = dPriv->x;
396 tmesa->drawY = dPriv->y;
397 }
398 }
399 else {
400 tmesa->numClipRects = dPriv->numBackClipRects;
401 tmesa->pClipRects = (drm_clip_rect_t *)dPriv->pBackClipRects;
402 tmesa->drawX = dPriv->backX;
403 tmesa->drawY = dPriv->backY;
404 }
405 break;
406 default:
407 return;
408 }
409
410 #if 0
411 tmesa->dirty |= TRIDENT_UPLOAD_CLIPRECTS;
412 #endif
413 }
414
415 #if 0
416 static GLboolean tridentDDSetDrawBuffer( GLcontext *ctx, GLenum mode )
417 {
418 tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx);
419 int found = GL_TRUE;
420
421 if ( tmesa->DrawBuffer != mode ) {
422 tmesa->DrawBuffer = mode;
423
424 switch ( mode ) {
425 case GL_FRONT_LEFT:
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 );
430 break;
431 case GL_BACK_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 );
436 break;
437 default:
438 tridentFallback( tmesa, TRIDENT_FALLBACK_DRAW_BUFFER, GL_TRUE );
439 found = GL_FALSE;
440 break;
441 }
442
443 #if 0
444 tmesa->setup.dst_off_pitch = (((tmesa->drawPitch/8) << 22) |
445 (tmesa->drawOffset >> 3));
446
447 tmesa->dirty |= MACH64_UPLOAD_DST_OFF_PITCH | MACH64_UPLOAD_CONTEXT;
448 #endif
449
450 }
451
452 return found;
453 }
454
455 static void tridentDDClearColor( GLcontext *ctx,
456 const GLchan color[4] )
457 {
458 tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx);
459
460 tmesa->ClearColor = tridentPackColor( tmesa->tridentScreen->cpp,
461 color[0], color[1],
462 color[2], color[3] );
463 }
464 #endif
465
466 static void
467 tridentDDUpdateState( GLcontext *ctx, GLuint new_state )
468 {
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;
474 }
475
476
477 /* Initialize the context's hardware state.
478 */
479 void tridentDDInitState( tridentContextPtr tmesa )
480 {
481 tmesa->new_state = 0;
482
483 switch ( tmesa->glCtx->Visual.depthBits ) {
484 case 16:
485 tmesa->depth_scale = 1.0 / (GLfloat)0xffff;
486 break;
487 case 24:
488 tmesa->depth_scale = 1.0 / (GLfloat)0xffffff;
489 break;
490 }
491 }
492
493 void tridentDDUpdateHWState( GLcontext *ctx )
494 {
495 tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx);
496 int new_state = tmesa->new_state;
497
498 if ( new_state )
499 {
500 tmesa->new_state = 0;
501
502 #if 0
503 /* Update the various parts of the context's state.
504 */
505 if ( new_state & GAMMA_NEW_ALPHA )
506 tridentUpdateAlphaMode( ctx );
507
508 if ( new_state & GAMMA_NEW_DEPTH )
509 tridentUpdateZMode( ctx );
510
511 if ( new_state & GAMMA_NEW_FOG )
512 gammaUpdateFogAttrib( ctx );
513
514 if ( new_state & GAMMA_NEW_CLIP )
515 gammaUpdateClipping( ctx );
516
517 if ( new_state & GAMMA_NEW_POLYGON )
518 gammaUpdatePolygon( ctx );
519
520 if ( new_state & GAMMA_NEW_CULL )
521 gammaUpdateCull( ctx );
522
523 if ( new_state & GAMMA_NEW_MASKS )
524 gammaUpdateMasks( ctx );
525
526 if ( new_state & GAMMA_NEW_STIPPLE )
527 gammaUpdateStipple( ctx );
528 #endif
529 }
530
531 /* HACK ! */
532
533 #if 0
534 gammaEmitHwState( tmesa );
535 #endif
536 }
537
538 /* Initialize the driver's state functions.
539 */
540 void tridentDDInitStateFuncs( GLcontext *ctx )
541 {
542 ctx->Driver.UpdateState = tridentDDUpdateState;
543
544 ctx->Driver.Clear = tridentDDClear;
545 ctx->Driver.DepthRange = tridentDDDepthRange;
546 ctx->Driver.ShadeModel = tridentDDShadeModel;
547 ctx->Driver.Viewport = tridentDDViewport;
548 }