3af3b7cd3dfe4c44462e16acbbb5aff2fcc3a9e9
[mesa.git] / src / mesa / drivers / glide / fxdd.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 5.1
4 *
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /* Authors:
26 * David Bucciarelli
27 * Brian Paul
28 * Daryll Strauss
29 * Keith Whitwell
30 * Daniel Borca
31 * Hiroshi Morii
32 */
33
34 /* fxdd.c - 3Dfx VooDoo Mesa device driver functions */
35
36
37 #ifdef HAVE_CONFIG_H
38 #include "conf.h"
39 #endif
40
41 #if defined(FX)
42
43 #include "image.h"
44 #include "mtypes.h"
45 #include "fxdrv.h"
46 #include "enums.h"
47 #include "extensions.h"
48 #include "macros.h"
49 #include "texstore.h"
50 #include "teximage.h"
51 #include "swrast/swrast.h"
52 #include "swrast/s_context.h"
53 #include "swrast_setup/swrast_setup.h"
54 #include "tnl/tnl.h"
55 #include "tnl/t_context.h"
56 #include "tnl/t_pipeline.h"
57 #include "array_cache/acache.h"
58
59
60
61 /* lookup table for scaling 4 bit colors up to 8 bits */
62 GLuint FX_rgb_scale_4[16] = {
63 0, 17, 34, 51, 68, 85, 102, 119,
64 136, 153, 170, 187, 204, 221, 238, 255
65 };
66
67 /* lookup table for scaling 5 bit colors up to 8 bits */
68 GLuint FX_rgb_scale_5[32] = {
69 0, 8, 16, 25, 33, 41, 49, 58,
70 66, 74, 82, 90, 99, 107, 115, 123,
71 132, 140, 148, 156, 165, 173, 181, 189,
72 197, 206, 214, 222, 230, 239, 247, 255
73 };
74
75 /* lookup table for scaling 6 bit colors up to 8 bits */
76 GLuint FX_rgb_scale_6[64] = {
77 0, 4, 8, 12, 16, 20, 24, 28,
78 32, 36, 40, 45, 49, 53, 57, 61,
79 65, 69, 73, 77, 81, 85, 89, 93,
80 97, 101, 105, 109, 113, 117, 121, 125,
81 130, 134, 138, 142, 146, 150, 154, 158,
82 162, 166, 170, 174, 178, 182, 186, 190,
83 194, 198, 202, 206, 210, 215, 219, 223,
84 227, 231, 235, 239, 243, 247, 251, 255
85 };
86
87
88 /*
89 * Disable color by masking out R, G, B, A
90 */
91 static void fxDisableColor (fxMesaContext fxMesa)
92 {
93 if (fxMesa->colDepth == 32) {
94 /* 32bpp mode */
95 fxMesa->Glide.grColorMaskExt(FXFALSE, FXFALSE, FXFALSE, FXFALSE);
96 } else {
97 /* 15/16 bpp mode */
98 grColorMask(FXFALSE, FXFALSE);
99 }
100 }
101
102
103 /**********************************************************************/
104 /***** Miscellaneous functions *****/
105 /**********************************************************************/
106
107 /* Return buffer size information */
108 static void
109 fxDDBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
110 {
111 GET_CURRENT_CONTEXT(ctx);
112 if (ctx && FX_CONTEXT(ctx)) {
113 fxMesaContext fxMesa = FX_CONTEXT(ctx);
114
115 if (TDFX_DEBUG & VERBOSE_DRIVER) {
116 fprintf(stderr, "fxDDBufferSize(...)\n");
117 }
118
119 *width = fxMesa->width;
120 *height = fxMesa->height;
121 }
122 }
123
124
125 /* Implements glClearColor() */
126 static void
127 fxDDClearColor(GLcontext * ctx, const GLfloat color[4])
128 {
129 fxMesaContext fxMesa = FX_CONTEXT(ctx);
130 GLubyte col[4];
131
132 if (TDFX_DEBUG & VERBOSE_DRIVER) {
133 fprintf(stderr, "fxDDClearColor(%f, %f, %f, %f)\n",
134 color[0], color[1], color[2], color[3]);
135 }
136
137 CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
138 CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
139 CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
140 CLAMPED_FLOAT_TO_UBYTE(col[3], color[3]);
141
142 fxMesa->clearC = FXCOLOR4(col);
143 fxMesa->clearA = col[3];
144 }
145
146
147 /* Clear the color and/or depth buffers */
148 static void fxDDClear( GLcontext *ctx,
149 GLbitfield mask, GLboolean all,
150 GLint x, GLint y, GLint width, GLint height )
151 {
152 fxMesaContext fxMesa = FX_CONTEXT(ctx);
153 GLbitfield softwareMask = mask & (DD_ACCUM_BIT);
154 const GLuint stencil_size = fxMesa->haveHwStencil ? ctx->Visual.stencilBits : 0;
155 const FxU32 clearD = (FxU32) (ctx->DepthMaxF * ctx->Depth.Clear);
156 const FxU8 clearS = (FxU8) (ctx->Stencil.Clear & 0xff);
157
158 if ( TDFX_DEBUG & MESA_VERBOSE ) {
159 fprintf( stderr, "fxDDClear( %d, %d, %d, %d )\n",
160 (int) x, (int) y, (int) width, (int) height );
161 }
162
163 /* we can't clear accum buffers nor stereo */
164 mask &= ~(DD_ACCUM_BIT | DD_FRONT_RIGHT_BIT | DD_BACK_RIGHT_BIT);
165
166 /* Need this check to respond to certain HW updates */
167 if (fxMesa->new_state & (FX_NEW_SCISSOR | FX_NEW_COLOR_MASK)) {
168 fxSetupScissor(ctx);
169 fxSetupColorMask(ctx);
170 fxMesa->new_state &= ~(FX_NEW_SCISSOR | FX_NEW_COLOR_MASK);
171 }
172
173 /*
174 * As per GL spec, color masking should be obeyed when clearing
175 */
176 if (ctx->Visual.greenBits != 8) {
177 /* can only do color masking if running in 24/32bpp on Napalm */
178 if (ctx->Color.ColorMask[RCOMP] != ctx->Color.ColorMask[GCOMP] ||
179 ctx->Color.ColorMask[GCOMP] != ctx->Color.ColorMask[BCOMP]) {
180 softwareMask |= (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT));
181 mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT);
182 }
183 }
184
185 if (fxMesa->haveHwStencil) {
186 /*
187 * If we want to clear stencil, it must be enabled
188 * in the HW, even if the stencil test is not enabled
189 * in the OGL state.
190 */
191 BEGIN_BOARD_LOCK();
192 if (mask & DD_STENCIL_BIT) {
193 fxMesa->Glide.grStencilMaskExt(fxMesa->unitsState.stencilWriteMask);
194 /* set stencil ref value = desired clear value */
195 fxMesa->Glide.grStencilFuncExt(GR_CMP_ALWAYS, clearS, 0xff);
196 fxMesa->Glide.grStencilOpExt(GR_STENCILOP_REPLACE,
197 GR_STENCILOP_REPLACE, GR_STENCILOP_REPLACE);
198 grEnable(GR_STENCIL_MODE_EXT);
199 }
200 else {
201 grDisable(GR_STENCIL_MODE_EXT);
202 }
203 END_BOARD_LOCK();
204 } else if (mask & DD_STENCIL_BIT) {
205 softwareMask |= (mask & (DD_STENCIL_BIT));
206 mask &= ~(DD_STENCIL_BIT);
207 }
208
209 /*
210 * This may be ugly, but it's needed in order to work around a number
211 * of Glide bugs.
212 */
213 BEGIN_CLIP_LOOP();
214 {
215 /*
216 * This could probably be done fancier but doing each possible case
217 * explicitly is less error prone.
218 */
219 switch (mask & ~DD_STENCIL_BIT) {
220 case DD_BACK_LEFT_BIT | DD_DEPTH_BIT:
221 /* back buffer & depth */
222 grDepthMask(FXTRUE);
223 grRenderBuffer(GR_BUFFER_BACKBUFFER);
224 if (stencil_size > 0) {
225 fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
226 fxMesa->clearA,
227 clearD, clearS);
228 }
229 else
230 grBufferClear(fxMesa->clearC,
231 fxMesa->clearA,
232 clearD);
233 break;
234 case DD_FRONT_LEFT_BIT | DD_DEPTH_BIT:
235 /* XXX it appears that the depth buffer isn't cleared when
236 * glRenderBuffer(GR_BUFFER_FRONTBUFFER) is set.
237 * This is a work-around/
238 */
239 /* clear depth */
240 grDepthMask(FXTRUE);
241 fxDisableColor(fxMesa);
242 grRenderBuffer(GR_BUFFER_BACKBUFFER);
243 if (stencil_size > 0)
244 fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
245 fxMesa->clearA,
246 clearD, clearS);
247 else
248 grBufferClear(fxMesa->clearC,
249 fxMesa->clearA,
250 clearD);
251 fxSetupColorMask(ctx);
252 grDepthMask(FXFALSE);
253 /* clear front */
254 grRenderBuffer(GR_BUFFER_FRONTBUFFER);
255 if (stencil_size > 0)
256 fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
257 fxMesa->clearA,
258 clearD, clearS);
259 else
260 grBufferClear(fxMesa->clearC,
261 fxMesa->clearA,
262 clearD);
263 break;
264 case DD_BACK_LEFT_BIT:
265 /* back buffer only */
266 grDepthMask(FXFALSE);
267 grRenderBuffer(GR_BUFFER_BACKBUFFER);
268 if (stencil_size > 0)
269 fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
270 fxMesa->clearA,
271 clearD, clearS);
272 else
273 grBufferClear(fxMesa->clearC,
274 fxMesa->clearA,
275 clearD);
276 break;
277 case DD_FRONT_LEFT_BIT:
278 /* front buffer only */
279 grDepthMask(FXFALSE);
280 grRenderBuffer(GR_BUFFER_FRONTBUFFER);
281 if (stencil_size > 0)
282 fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
283 fxMesa->clearA,
284 clearD, clearS);
285 else
286 grBufferClear(fxMesa->clearC,
287 fxMesa->clearA,
288 clearD);
289 break;
290 case DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT:
291 /* front and back */
292 grDepthMask(FXFALSE);
293 grRenderBuffer(GR_BUFFER_BACKBUFFER);
294 if (stencil_size > 0)
295 fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
296 fxMesa->clearA,
297 clearD, clearS);
298 else
299 grBufferClear(fxMesa->clearC,
300 fxMesa->clearA,
301 clearD);
302 grRenderBuffer(GR_BUFFER_FRONTBUFFER);
303 if (stencil_size > 0)
304 fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
305 fxMesa->clearA,
306 clearD, clearS);
307 else
308 grBufferClear(fxMesa->clearC,
309 fxMesa->clearA,
310 clearD);
311 break;
312 case DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT | DD_DEPTH_BIT:
313 /* clear back and depth */
314 grDepthMask(FXTRUE);
315 grRenderBuffer(GR_BUFFER_BACKBUFFER);
316 if (stencil_size > 0)
317 fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
318 fxMesa->clearA,
319 clearD, clearS);
320 else
321 grBufferClear(fxMesa->clearC,
322 fxMesa->clearA,
323 clearD);
324 /* clear front */
325 grDepthMask(FXFALSE);
326 grRenderBuffer(GR_BUFFER_FRONTBUFFER);
327 if (stencil_size > 0)
328 fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
329 fxMesa->clearA,
330 clearD, clearS);
331 else
332 grBufferClear(fxMesa->clearC,
333 fxMesa->clearA,
334 clearD);
335 break;
336 case DD_DEPTH_BIT:
337 /* just the depth buffer */
338 grDepthMask(FXTRUE);
339 fxDisableColor(fxMesa);
340 grRenderBuffer(GR_BUFFER_BACKBUFFER);
341 if (stencil_size > 0)
342 fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
343 fxMesa->clearA,
344 clearD, clearS);
345 else
346 grBufferClear(fxMesa->clearC,
347 fxMesa->clearA,
348 clearD);
349 fxSetupColorMask(ctx);
350 break;
351 default:
352 /* clear no color buffers or depth buffer but might clear stencil */
353 if ((stencil_size > 0) && (mask & DD_STENCIL_BIT)) {
354 /* XXX need this RenderBuffer call to work around Glide bug */
355 grDepthMask(FXFALSE);
356 grRenderBuffer(GR_BUFFER_BACKBUFFER);
357 fxDisableColor(fxMesa);
358 fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
359 fxMesa->clearA,
360 clearD, clearS);
361 fxSetupColorMask(ctx);
362 }
363 }
364 }
365 END_CLIP_LOOP();
366
367 if (fxMesa->haveHwStencil) {
368 /* We changed the stencil state above. Restore it! */
369 fxSetupStencil(ctx);
370 }
371 fxSetupDepthTest(ctx);
372 grRenderBuffer(fxMesa->currentFB);
373
374 if (softwareMask)
375 _swrast_Clear( ctx, softwareMask, all, x, y, width, height );
376 }
377
378
379 /* Set the buffer used for drawing */
380 /* XXX support for separate read/draw buffers hasn't been tested */
381 /* XXX GL_NONE disables color, but fails to correctly maintain state */
382 static void
383 fxDDSetDrawBuffer(GLcontext * ctx, GLenum mode)
384 {
385 fxMesaContext fxMesa = FX_CONTEXT(ctx);
386
387 if (TDFX_DEBUG & VERBOSE_DRIVER) {
388 fprintf(stderr, "fxDDSetDrawBuffer(%x)\n", (int)mode);
389 }
390
391 if (mode == GL_FRONT_LEFT) {
392 fxMesa->currentFB = GR_BUFFER_FRONTBUFFER;
393 grRenderBuffer(fxMesa->currentFB);
394 }
395 else if (mode == GL_BACK_LEFT) {
396 fxMesa->currentFB = GR_BUFFER_BACKBUFFER;
397 grRenderBuffer(fxMesa->currentFB);
398 }
399 else if (mode == GL_NONE) {
400 fxDisableColor(fxMesa);
401 }
402 else {
403 /* we'll need a software fallback */
404 /* XXX not implemented */
405 }
406
407 /* update s/w fallback state */
408 _swrast_DrawBuffer(ctx, mode);
409 }
410
411
412 static void
413 fxDDDrawBitmap2 (GLcontext *ctx, GLint px, GLint py,
414 GLsizei width, GLsizei height,
415 const struct gl_pixelstore_attrib *unpack,
416 const GLubyte *bitmap)
417 {
418 fxMesaContext fxMesa = FX_CONTEXT(ctx);
419 SWcontext *swrast = SWRAST_CONTEXT(ctx);
420 GrLfbInfo_t info;
421 GrLfbWriteMode_t mode;
422 FxU16 color;
423 const struct gl_pixelstore_attrib *finalUnpack;
424 struct gl_pixelstore_attrib scissoredUnpack;
425
426 /* check if there's any raster operations enabled which we can't handle */
427 if (swrast->_RasterMask & (ALPHATEST_BIT |
428 /*BLEND_BIT |*/ /* blending ok, through pixpipe */
429 DEPTH_BIT | /* could be done with RGB:DEPTH */
430 FOG_BIT | /* could be done with RGB:DEPTH */
431 LOGIC_OP_BIT |
432 /*CLIP_BIT |*/ /* clipping ok, below */
433 STENCIL_BIT |
434 MASKING_BIT |
435 ALPHABUF_BIT | /* nope! see 565 span kludge */
436 MULTI_DRAW_BIT |
437 OCCLUSION_BIT | /* nope! at least not yet */
438 TEXTURE_BIT |
439 FRAGPROG_BIT)) {
440 _swrast_Bitmap(ctx, px, py, width, height, unpack, bitmap);
441 return;
442 }
443
444 /* make sure the pixelpipe is configured correctly */
445 fxSetupFXUnits(ctx);
446
447 /* FIXME! _RasterMask & CLIP_BIT gets set if we're out of Viewport, also! */
448 if (ctx->Scissor.Enabled) {
449 /* This is a bit tricky, but by carefully adjusting the px, py,
450 * width, height, skipPixels and skipRows values we can do
451 * scissoring without special code in the rendering loop.
452 */
453
454 /* we'll construct a new pixelstore struct */
455 finalUnpack = &scissoredUnpack;
456 scissoredUnpack = *unpack;
457 if (scissoredUnpack.RowLength == 0)
458 scissoredUnpack.RowLength = width;
459
460 /* clip left */
461 if (px < ctx->Scissor.X) {
462 scissoredUnpack.SkipPixels += (ctx->Scissor.X - px);
463 width -= (ctx->Scissor.X - px);
464 px = ctx->Scissor.X;
465 }
466 /* clip right */
467 if (px + width >= ctx->Scissor.X + ctx->Scissor.Width) {
468 width -= (px + width - (ctx->Scissor.X + ctx->Scissor.Width));
469 }
470 /* clip bottom */
471 if (py < ctx->Scissor.Y) {
472 scissoredUnpack.SkipRows += (ctx->Scissor.Y - py);
473 height -= (ctx->Scissor.Y - py);
474 py = ctx->Scissor.Y;
475 }
476 /* clip top */
477 if (py + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
478 height -= (py + height - (ctx->Scissor.Y + ctx->Scissor.Height));
479 }
480
481 if (width <= 0 || height <= 0)
482 return;
483 }
484 else {
485 finalUnpack = unpack;
486 }
487
488 /* compute pixel value */
489 {
490 GLint r = (GLint) (ctx->Current.RasterColor[RCOMP] * 255.0f);
491 GLint g = (GLint) (ctx->Current.RasterColor[GCOMP] * 255.0f);
492 GLint b = (GLint) (ctx->Current.RasterColor[BCOMP] * 255.0f);
493 GLint a = (GLint) (ctx->Current.RasterColor[ACOMP] * 255.0f);
494 if (fxMesa->colDepth == 15) {
495 color = TDFXPACKCOLOR1555(b, g, r, a);
496 mode = GR_LFBWRITEMODE_1555;
497 } else {
498 color = fxMesa->bgrOrder ? TDFXPACKCOLOR565(r, g, b) : TDFXPACKCOLOR565(b, g, r);
499 mode = GR_LFBWRITEMODE_565;
500 }
501 }
502
503 info.size = sizeof(info);
504 if (!grLfbLock(GR_LFB_WRITE_ONLY,
505 fxMesa->currentFB,
506 mode,
507 GR_ORIGIN_LOWER_LEFT, FXTRUE, &info)) {
508 _swrast_Bitmap(ctx, px, py, width, height, finalUnpack, bitmap);
509 return;
510 }
511
512 {
513 const GLint winX = 0;
514 const GLint winY = 0;
515 /* The dest stride depends on the hardware and whether we're drawing
516 * to the front or back buffer. This compile-time test seems to do
517 * the job for now.
518 */
519 const GLint dstStride = info.strideInBytes / 2; /* stride in GLushorts */
520
521 GLint row;
522 /* compute dest address of bottom-left pixel in bitmap */
523 GLushort *dst = (GLushort *) info.lfbPtr
524 + (winY + py) * dstStride + (winX + px);
525
526 for (row = 0; row < height; row++) {
527 const GLubyte *src =
528 (const GLubyte *) _mesa_image_address(finalUnpack,
529 bitmap, width, height,
530 GL_COLOR_INDEX, GL_BITMAP,
531 0, row, 0);
532 if (finalUnpack->LsbFirst) {
533 /* least significan bit first */
534 GLubyte mask = 1U << (finalUnpack->SkipPixels & 0x7);
535 GLint col;
536 for (col = 0; col < width; col++) {
537 if (*src & mask) {
538 dst[col] = color;
539 }
540 if (mask == 128U) {
541 src++;
542 mask = 1U;
543 }
544 else {
545 mask = mask << 1;
546 }
547 }
548 if (mask != 1)
549 src++;
550 }
551 else {
552 /* most significan bit first */
553 GLubyte mask = 128U >> (finalUnpack->SkipPixels & 0x7);
554 GLint col;
555 for (col = 0; col < width; col++) {
556 if (*src & mask) {
557 dst[col] = color;
558 }
559 if (mask == 1U) {
560 src++;
561 mask = 128U;
562 }
563 else {
564 mask = mask >> 1;
565 }
566 }
567 if (mask != 128)
568 src++;
569 }
570 dst += dstStride;
571 }
572 }
573
574 grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
575 }
576
577 static void
578 fxDDDrawBitmap4 (GLcontext *ctx, GLint px, GLint py,
579 GLsizei width, GLsizei height,
580 const struct gl_pixelstore_attrib *unpack,
581 const GLubyte *bitmap)
582 {
583 fxMesaContext fxMesa = FX_CONTEXT(ctx);
584 SWcontext *swrast = SWRAST_CONTEXT(ctx);
585 GrLfbInfo_t info;
586 FxU32 color;
587 const struct gl_pixelstore_attrib *finalUnpack;
588 struct gl_pixelstore_attrib scissoredUnpack;
589
590 /* check if there's any raster operations enabled which we can't handle */
591 if ((swrast->_RasterMask & (/*ALPHATEST_BIT |*/
592 /*BLEND_BIT |*/ /* blending ok, through pixpipe */
593 DEPTH_BIT | /* could be done with RGB:DEPTH */
594 FOG_BIT | /* could be done with RGB:DEPTH */
595 LOGIC_OP_BIT |
596 /*CLIP_BIT |*/ /* clipping ok, below */
597 STENCIL_BIT |
598 /*MASKING_BIT |*/ /* masking ok, we're in 32bpp */
599 /*ALPHABUF_BIT |*//* alpha ok, we're in 32bpp */
600 MULTI_DRAW_BIT |
601 OCCLUSION_BIT | /* nope! at least not yet */
602 TEXTURE_BIT |
603 FRAGPROG_BIT))
604 ) {
605 _swrast_Bitmap(ctx, px, py, width, height, unpack, bitmap);
606 return;
607 }
608
609 /* make sure the pixelpipe is configured correctly */
610 fxSetupFXUnits(ctx);
611
612 /* FIXME! _RasterMask & CLIP_BIT gets set if we're out of Viewport, also! */
613 if (ctx->Scissor.Enabled) {
614 /* This is a bit tricky, but by carefully adjusting the px, py,
615 * width, height, skipPixels and skipRows values we can do
616 * scissoring without special code in the rendering loop.
617 */
618
619 /* we'll construct a new pixelstore struct */
620 finalUnpack = &scissoredUnpack;
621 scissoredUnpack = *unpack;
622 if (scissoredUnpack.RowLength == 0)
623 scissoredUnpack.RowLength = width;
624
625 /* clip left */
626 if (px < ctx->Scissor.X) {
627 scissoredUnpack.SkipPixels += (ctx->Scissor.X - px);
628 width -= (ctx->Scissor.X - px);
629 px = ctx->Scissor.X;
630 }
631 /* clip right */
632 if (px + width >= ctx->Scissor.X + ctx->Scissor.Width) {
633 width -= (px + width - (ctx->Scissor.X + ctx->Scissor.Width));
634 }
635 /* clip bottom */
636 if (py < ctx->Scissor.Y) {
637 scissoredUnpack.SkipRows += (ctx->Scissor.Y - py);
638 height -= (ctx->Scissor.Y - py);
639 py = ctx->Scissor.Y;
640 }
641 /* clip top */
642 if (py + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
643 height -= (py + height - (ctx->Scissor.Y + ctx->Scissor.Height));
644 }
645
646 if (width <= 0 || height <= 0)
647 return;
648 }
649 else {
650 finalUnpack = unpack;
651 }
652
653 /* compute pixel value */
654 {
655 GLint r = (GLint) (ctx->Current.RasterColor[RCOMP] * 255.0f);
656 GLint g = (GLint) (ctx->Current.RasterColor[GCOMP] * 255.0f);
657 GLint b = (GLint) (ctx->Current.RasterColor[BCOMP] * 255.0f);
658 GLint a = (GLint) (ctx->Current.RasterColor[ACOMP] * 255.0f);
659 color = TDFXPACKCOLOR8888(b, g, r, a);
660 }
661
662 info.size = sizeof(info);
663 if (!grLfbLock(GR_LFB_WRITE_ONLY,
664 fxMesa->currentFB,
665 GR_LFBWRITEMODE_8888,
666 GR_ORIGIN_LOWER_LEFT, FXTRUE, &info)) {
667 _swrast_Bitmap(ctx, px, py, width, height, finalUnpack, bitmap);
668 return;
669 }
670
671 {
672 const GLint winX = 0;
673 const GLint winY = 0;
674 /* The dest stride depends on the hardware and whether we're drawing
675 * to the front or back buffer. This compile-time test seems to do
676 * the job for now.
677 */
678 const GLint dstStride = info.strideInBytes / 4; /* stride in GLuints */
679
680 GLint row;
681 /* compute dest address of bottom-left pixel in bitmap */
682 GLuint *dst = (GLuint *) info.lfbPtr
683 + (winY + py) * dstStride + (winX + px);
684
685 for (row = 0; row < height; row++) {
686 const GLubyte *src =
687 (const GLubyte *) _mesa_image_address(finalUnpack,
688 bitmap, width, height,
689 GL_COLOR_INDEX, GL_BITMAP,
690 0, row, 0);
691 if (finalUnpack->LsbFirst) {
692 /* least significan bit first */
693 GLubyte mask = 1U << (finalUnpack->SkipPixels & 0x7);
694 GLint col;
695 for (col = 0; col < width; col++) {
696 if (*src & mask) {
697 dst[col] = color;
698 }
699 if (mask == 128U) {
700 src++;
701 mask = 1U;
702 }
703 else {
704 mask = mask << 1;
705 }
706 }
707 if (mask != 1)
708 src++;
709 }
710 else {
711 /* most significan bit first */
712 GLubyte mask = 128U >> (finalUnpack->SkipPixels & 0x7);
713 GLint col;
714 for (col = 0; col < width; col++) {
715 if (*src & mask) {
716 dst[col] = color;
717 }
718 if (mask == 1U) {
719 src++;
720 mask = 128U;
721 }
722 else {
723 mask = mask >> 1;
724 }
725 }
726 if (mask != 128)
727 src++;
728 }
729 dst += dstStride;
730 }
731 }
732
733 grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
734 }
735
736
737 static void
738 fxDDReadPixels565 (GLcontext * ctx,
739 GLint x, GLint y,
740 GLsizei width, GLsizei height,
741 GLenum format, GLenum type,
742 const struct gl_pixelstore_attrib *packing,
743 GLvoid *dstImage)
744 {
745 if (ctx->_ImageTransferState/* & (IMAGE_SCALE_BIAS_BIT|IMAGE_MAP_COLOR_BIT)*/) {
746 _swrast_ReadPixels(ctx, x, y, width, height, format, type,
747 packing, dstImage);
748 return;
749 }
750 else {
751 fxMesaContext fxMesa = FX_CONTEXT(ctx);
752 GrLfbInfo_t info;
753
754 BEGIN_BOARD_LOCK();
755 info.size = sizeof(info);
756 if (grLfbLock(GR_LFB_READ_ONLY,
757 fxMesa->currentFB,
758 GR_LFBWRITEMODE_ANY,
759 GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
760 const GLint winX = 0;
761 const GLint winY = fxMesa->height - 1;
762 const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */
763 const GLushort *src = (const GLushort *) info.lfbPtr
764 + (winY - y) * srcStride + (winX + x);
765 GLubyte *dst = (GLubyte *) _mesa_image_address(packing, dstImage,
766 width, height, format,
767 type, 0, 0, 0);
768 GLint dstStride =
769 _mesa_image_row_stride(packing, width, format, type);
770
771 if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
772 /* convert 5R6G5B into 8R8G8B */
773 GLint row, col;
774 const GLint halfWidth = width >> 1;
775 const GLint extraPixel = (width & 1);
776 for (row = 0; row < height; row++) {
777 GLubyte *d = dst;
778 for (col = 0; col < halfWidth; col++) {
779 const GLuint pixel = ((const GLuint *) src)[col];
780 *d++ = FX_rgb_scale_5[(pixel >> 11) & 0x1f];
781 *d++ = FX_rgb_scale_6[(pixel >> 5) & 0x3f];
782 *d++ = FX_rgb_scale_5[ pixel & 0x1f];
783 *d++ = FX_rgb_scale_5[(pixel >> 27) & 0x1f];
784 *d++ = FX_rgb_scale_6[(pixel >> 21) & 0x3f];
785 *d++ = FX_rgb_scale_5[(pixel >> 16) & 0x1f];
786 }
787 if (extraPixel) {
788 GLushort pixel = src[width - 1];
789 *d++ = FX_rgb_scale_5[(pixel >> 11) & 0x1f];
790 *d++ = FX_rgb_scale_6[(pixel >> 5) & 0x3f];
791 *d++ = FX_rgb_scale_5[ pixel & 0x1f];
792 }
793 dst += dstStride;
794 src -= srcStride;
795 }
796 }
797 else if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
798 /* convert 5R6G5B into 8R8G8B8A */
799 GLint row, col;
800 const GLint halfWidth = width >> 1;
801 const GLint extraPixel = (width & 1);
802 for (row = 0; row < height; row++) {
803 GLubyte *d = dst;
804 for (col = 0; col < halfWidth; col++) {
805 const GLuint pixel = ((const GLuint *) src)[col];
806 *d++ = FX_rgb_scale_5[(pixel >> 11) & 0x1f];
807 *d++ = FX_rgb_scale_6[(pixel >> 5) & 0x3f];
808 *d++ = FX_rgb_scale_5[ pixel & 0x1f];
809 *d++ = 255;
810 *d++ = FX_rgb_scale_5[(pixel >> 27) & 0x1f];
811 *d++ = FX_rgb_scale_6[(pixel >> 21) & 0x3f];
812 *d++ = FX_rgb_scale_5[(pixel >> 16) & 0x1f];
813 *d++ = 255;
814 }
815 if (extraPixel) {
816 const GLushort pixel = src[width - 1];
817 *d++ = FX_rgb_scale_5[(pixel >> 11) & 0x1f];
818 *d++ = FX_rgb_scale_6[(pixel >> 5) & 0x3f];
819 *d++ = FX_rgb_scale_5[ pixel & 0x1f];
820 *d++ = 255;
821 }
822 dst += dstStride;
823 src -= srcStride;
824 }
825 }
826 else if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
827 /* directly memcpy 5R6G5B pixels into client's buffer */
828 const GLint widthInBytes = width * 2;
829 GLint row;
830 for (row = 0; row < height; row++) {
831 MEMCPY(dst, src, widthInBytes);
832 dst += dstStride;
833 src -= srcStride;
834 }
835 }
836 else {
837 grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
838 END_BOARD_LOCK();
839 _swrast_ReadPixels(ctx, x, y, width, height, format, type,
840 packing, dstImage);
841 return;
842 }
843
844 grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
845 }
846 END_BOARD_LOCK();
847 }
848 }
849
850 static void
851 fxDDReadPixels555 (GLcontext * ctx,
852 GLint x, GLint y,
853 GLsizei width, GLsizei height,
854 GLenum format, GLenum type,
855 const struct gl_pixelstore_attrib *packing,
856 GLvoid *dstImage)
857 {
858 if (ctx->_ImageTransferState/* & (IMAGE_SCALE_BIAS_BIT|IMAGE_MAP_COLOR_BIT)*/) {
859 _swrast_ReadPixels(ctx, x, y, width, height, format, type,
860 packing, dstImage);
861 return;
862 }
863 else {
864 fxMesaContext fxMesa = FX_CONTEXT(ctx);
865 GrLfbInfo_t info;
866
867 BEGIN_BOARD_LOCK();
868 info.size = sizeof(info);
869 if (grLfbLock(GR_LFB_READ_ONLY,
870 fxMesa->currentFB,
871 GR_LFBWRITEMODE_ANY,
872 GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
873 const GLint winX = 0;
874 const GLint winY = fxMesa->height - 1;
875 const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */
876 const GLushort *src = (const GLushort *) info.lfbPtr
877 + (winY - y) * srcStride + (winX + x);
878 GLubyte *dst = (GLubyte *) _mesa_image_address(packing, dstImage,
879 width, height, format,
880 type, 0, 0, 0);
881 GLint dstStride =
882 _mesa_image_row_stride(packing, width, format, type);
883
884 if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
885 /* convert 5R5G5B into 8R8G8B */
886 GLint row, col;
887 const GLint halfWidth = width >> 1;
888 const GLint extraPixel = (width & 1);
889 for (row = 0; row < height; row++) {
890 GLubyte *d = dst;
891 for (col = 0; col < halfWidth; col++) {
892 const GLuint pixel = ((const GLuint *) src)[col];
893 *d++ = FX_rgb_scale_5[(pixel >> 10) & 0x1f];
894 *d++ = FX_rgb_scale_5[(pixel >> 5) & 0x1f];
895 *d++ = FX_rgb_scale_5[ pixel & 0x1f];
896 *d++ = FX_rgb_scale_5[(pixel >> 26) & 0x1f];
897 *d++ = FX_rgb_scale_5[(pixel >> 21) & 0x1f];
898 *d++ = FX_rgb_scale_5[(pixel >> 16) & 0x1f];
899 }
900 if (extraPixel) {
901 GLushort pixel = src[width - 1];
902 *d++ = FX_rgb_scale_5[(pixel >> 10) & 0x1f];
903 *d++ = FX_rgb_scale_5[(pixel >> 5) & 0x1f];
904 *d++ = FX_rgb_scale_5[ pixel & 0x1f];
905 }
906 dst += dstStride;
907 src -= srcStride;
908 }
909 }
910 else if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
911 /* convert 5R6G5B into 8R8G8B8A */
912 GLint row, col;
913 const GLint halfWidth = width >> 1;
914 const GLint extraPixel = (width & 1);
915 for (row = 0; row < height; row++) {
916 GLubyte *d = dst;
917 for (col = 0; col < halfWidth; col++) {
918 const GLuint pixel = ((const GLuint *) src)[col];
919 *d++ = FX_rgb_scale_5[(pixel >> 10) & 0x1f];
920 *d++ = FX_rgb_scale_5[(pixel >> 5) & 0x1f];
921 *d++ = FX_rgb_scale_5[ pixel & 0x1f];
922 *d++ = (pixel & 0x8000) ? 255 : 0;
923 *d++ = FX_rgb_scale_5[(pixel >> 26) & 0x1f];
924 *d++ = FX_rgb_scale_5[(pixel >> 21) & 0x1f];
925 *d++ = FX_rgb_scale_5[(pixel >> 16) & 0x1f];
926 *d++ = (pixel & 0x80000000) ? 255 : 0;
927 }
928 if (extraPixel) {
929 const GLushort pixel = src[width - 1];
930 *d++ = FX_rgb_scale_5[(pixel >> 10) & 0x1f];
931 *d++ = FX_rgb_scale_5[(pixel >> 5) & 0x1f];
932 *d++ = FX_rgb_scale_5[ pixel & 0x1f];
933 *d++ = (pixel & 0x8000) ? 255 : 0;
934 }
935 dst += dstStride;
936 src -= srcStride;
937 }
938 }
939 else if (format == GL_BGRA && type == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
940 /* directly memcpy 5R5G5B pixels into client's buffer */
941 const GLint widthInBytes = width * 2;
942 GLint row;
943 for (row = 0; row < height; row++) {
944 MEMCPY(dst, src, widthInBytes);
945 dst += dstStride;
946 src -= srcStride;
947 }
948 }
949 else {
950 grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
951 END_BOARD_LOCK();
952 _swrast_ReadPixels(ctx, x, y, width, height, format, type,
953 packing, dstImage);
954 return;
955 }
956
957 grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
958 }
959 END_BOARD_LOCK();
960 }
961 }
962
963 static void
964 fxDDReadPixels8888 (GLcontext * ctx,
965 GLint x, GLint y,
966 GLsizei width, GLsizei height,
967 GLenum format, GLenum type,
968 const struct gl_pixelstore_attrib *packing,
969 GLvoid *dstImage)
970 {
971 if (ctx->_ImageTransferState/* & (IMAGE_SCALE_BIAS_BIT|IMAGE_MAP_COLOR_BIT)*/) {
972 _swrast_ReadPixels(ctx, x, y, width, height, format, type,
973 packing, dstImage);
974 return;
975 }
976 else {
977 fxMesaContext fxMesa = FX_CONTEXT(ctx);
978 GrLfbInfo_t info;
979
980 BEGIN_BOARD_LOCK();
981 info.size = sizeof(info);
982 if (grLfbLock(GR_LFB_READ_ONLY,
983 fxMesa->currentFB,
984 GR_LFBWRITEMODE_ANY,
985 GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
986 const GLint winX = 0;
987 const GLint winY = fxMesa->height - 1;
988 const GLint srcStride = info.strideInBytes / 4; /* stride in GLuints */
989 const GLuint *src = (const GLuint *) info.lfbPtr
990 + (winY - y) * srcStride + (winX + x);
991 GLubyte *dst = (GLubyte *) _mesa_image_address(packing, dstImage,
992 width, height, format,
993 type, 0, 0, 0);
994 GLint dstStride =
995 _mesa_image_row_stride(packing, width, format, type);
996
997 if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
998 /* convert 8A8R8G8B into 8R8G8B */
999 GLint row, col;
1000 for (row = 0; row < height; row++) {
1001 GLubyte *d = dst;
1002 for (col = 0; col < width; col++) {
1003 const GLuint pixel = ((const GLuint *) src)[col];
1004 *d++ = pixel >> 16;
1005 *d++ = pixel >> 8;
1006 *d++ = pixel;
1007 }
1008 dst += dstStride;
1009 src -= srcStride;
1010 }
1011 }
1012 else if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
1013 /* 8A8R8G8B pixels into client's buffer */
1014 GLint row, col;
1015 for (row = 0; row < height; row++) {
1016 GLubyte *d = dst;
1017 for (col = 0; col < width; col++) {
1018 const GLuint pixel = ((const GLuint *) src)[col];
1019 *d++ = pixel >> 16;
1020 *d++ = pixel >> 8;
1021 *d++ = pixel;
1022 *d++ = pixel >> 24;
1023 }
1024 dst += dstStride;
1025 src -= srcStride;
1026 }
1027 }
1028 else if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
1029 /* convert 8A8R8G8B into 5R6G5B */
1030 GLint row, col;
1031 for (row = 0; row < height; row++) {
1032 GLushort *d = (GLushort *)dst;
1033 for (col = 0; col < width; col++) {
1034 const GLuint pixel = ((const GLuint *) src)[col];
1035 *d++ = (((pixel >> 16) & 0xf8) << 8) |
1036 (((pixel >> 8) & 0xfc) << 3) |
1037 ((pixel & 0xf8) >> 3);
1038 }
1039 dst += dstStride;
1040 src -= srcStride;
1041 }
1042 }
1043 else {
1044 grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
1045 END_BOARD_LOCK();
1046 _swrast_ReadPixels(ctx, x, y, width, height, format, type,
1047 packing, dstImage);
1048 return;
1049 }
1050
1051 grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
1052 }
1053 END_BOARD_LOCK();
1054 }
1055 }
1056
1057
1058 void
1059 fxDDDrawPixels555 (GLcontext * ctx, GLint x, GLint y,
1060 GLsizei width, GLsizei height,
1061 GLenum format, GLenum type,
1062 const struct gl_pixelstore_attrib *unpack,
1063 const GLvoid * pixels)
1064 {
1065 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1066 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1067 GrLfbInfo_t info;
1068 const struct gl_pixelstore_attrib *finalUnpack;
1069 struct gl_pixelstore_attrib scissoredUnpack;
1070
1071 if (ctx->Pixel.ZoomX != 1.0F ||
1072 ctx->Pixel.ZoomY != 1.0F ||
1073 (ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
1074 IMAGE_MAP_COLOR_BIT)) ||
1075 (swrast->_RasterMask & (ALPHATEST_BIT |
1076 /*BLEND_BIT |*/ /* blending ok, through pixpipe */
1077 DEPTH_BIT | /* could be done with RGB:DEPTH */
1078 FOG_BIT | /* could be done with RGB:DEPTH */
1079 LOGIC_OP_BIT |
1080 /*CLIP_BIT |*/ /* clipping ok, below */
1081 STENCIL_BIT |
1082 MASKING_BIT |
1083 ALPHABUF_BIT |
1084 MULTI_DRAW_BIT |
1085 OCCLUSION_BIT | /* nope! at least not yet */
1086 TEXTURE_BIT |
1087 FRAGPROG_BIT)) ||
1088 fxMesa->fallback)
1089 {
1090 _swrast_DrawPixels( ctx, x, y, width, height, format, type,
1091 unpack, pixels );
1092 return;
1093 }
1094
1095 /* make sure the pixelpipe is configured correctly */
1096 fxSetupFXUnits(ctx);
1097
1098 /* FIXME! _RasterMask & CLIP_BIT gets set if we're out of Viewport, also! */
1099 if (ctx->Scissor.Enabled) {
1100 /* This is a bit tricky, but by carefully adjusting the px, py,
1101 * width, height, skipPixels and skipRows values we can do
1102 * scissoring without special code in the rendering loop.
1103 */
1104
1105 /* we'll construct a new pixelstore struct */
1106 finalUnpack = &scissoredUnpack;
1107 scissoredUnpack = *unpack;
1108 if (scissoredUnpack.RowLength == 0)
1109 scissoredUnpack.RowLength = width;
1110
1111 /* clip left */
1112 if (x < ctx->Scissor.X) {
1113 scissoredUnpack.SkipPixels += (ctx->Scissor.X - x);
1114 width -= (ctx->Scissor.X - x);
1115 x = ctx->Scissor.X;
1116 }
1117 /* clip right */
1118 if (x + width >= ctx->Scissor.X + ctx->Scissor.Width) {
1119 width -= (x + width - (ctx->Scissor.X + ctx->Scissor.Width));
1120 }
1121 /* clip bottom */
1122 if (y < ctx->Scissor.Y) {
1123 scissoredUnpack.SkipRows += (ctx->Scissor.Y - y);
1124 height -= (ctx->Scissor.Y - y);
1125 y = ctx->Scissor.Y;
1126 }
1127 /* clip top */
1128 if (y + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
1129 height -= (y + height - (ctx->Scissor.Y + ctx->Scissor.Height));
1130 }
1131
1132 if (width <= 0 || height <= 0)
1133 return;
1134 }
1135 else {
1136 finalUnpack = unpack;
1137 }
1138
1139 info.size = sizeof(info);
1140 if (!grLfbLock(GR_LFB_WRITE_ONLY,
1141 fxMesa->currentFB,
1142 GR_LFBWRITEMODE_1555,
1143 GR_ORIGIN_LOWER_LEFT, FXTRUE, &info)) {
1144 _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
1145 return;
1146 }
1147
1148 {
1149 const GLint winX = 0;
1150 const GLint winY = 0;
1151
1152 const GLint dstStride = info.strideInBytes / 2; /* stride in GLushorts */
1153 GLushort *dst = (GLushort *) info.lfbPtr + (winY + y) * dstStride + (winX + x);
1154
1155 if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
1156 GLint row;
1157 for (row = 0; row < height; row++) {
1158 GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
1159 width, height, format,
1160 type, 0, row, 0);
1161 GLint col;
1162 for (col = 0; col < width; col++) {
1163 dst[col] = TDFXPACKCOLOR1555(src[2], src[1], src[0], src[3]);
1164 src += 4;
1165 }
1166 dst += dstStride;
1167 }
1168 }
1169 else if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
1170 GLint row;
1171 for (row = 0; row < height; row++) {
1172 GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
1173 width, height, format,
1174 type, 0, row, 0);
1175 GLint col;
1176 for (col = 0; col < width; col++) {
1177 dst[col] = TDFXPACKCOLOR1555(src[2], src[1], src[0], 255);
1178 src += 3;
1179 }
1180 dst += dstStride;
1181 }
1182 }
1183 else {
1184 grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
1185 _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
1186 return;
1187 }
1188
1189 }
1190
1191 grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
1192 }
1193
1194
1195 void
1196 fxDDDrawPixels565 (GLcontext * ctx, GLint x, GLint y,
1197 GLsizei width, GLsizei height,
1198 GLenum format, GLenum type,
1199 const struct gl_pixelstore_attrib *unpack,
1200 const GLvoid * pixels)
1201 {
1202 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1203 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1204 GrLfbInfo_t info;
1205 const struct gl_pixelstore_attrib *finalUnpack;
1206 struct gl_pixelstore_attrib scissoredUnpack;
1207
1208 if (ctx->Pixel.ZoomX != 1.0F ||
1209 ctx->Pixel.ZoomY != 1.0F ||
1210 (ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
1211 IMAGE_MAP_COLOR_BIT)) ||
1212 (swrast->_RasterMask & (ALPHATEST_BIT |
1213 /*BLEND_BIT |*/ /* blending ok, through pixpipe */
1214 DEPTH_BIT | /* could be done with RGB:DEPTH */
1215 FOG_BIT | /* could be done with RGB:DEPTH */
1216 LOGIC_OP_BIT |
1217 /*CLIP_BIT |*/ /* clipping ok, below */
1218 STENCIL_BIT |
1219 MASKING_BIT |
1220 ALPHABUF_BIT |
1221 MULTI_DRAW_BIT |
1222 OCCLUSION_BIT | /* nope! at least not yet */
1223 TEXTURE_BIT |
1224 FRAGPROG_BIT)) ||
1225 fxMesa->fallback)
1226 {
1227 _swrast_DrawPixels( ctx, x, y, width, height, format, type,
1228 unpack, pixels );
1229 return;
1230 }
1231
1232 /* make sure the pixelpipe is configured correctly */
1233 fxSetupFXUnits(ctx);
1234
1235 /* FIXME! _RasterMask & CLIP_BIT gets set if we're out of Viewport, also! */
1236 if (ctx->Scissor.Enabled) {
1237 /* This is a bit tricky, but by carefully adjusting the px, py,
1238 * width, height, skipPixels and skipRows values we can do
1239 * scissoring without special code in the rendering loop.
1240 */
1241
1242 /* we'll construct a new pixelstore struct */
1243 finalUnpack = &scissoredUnpack;
1244 scissoredUnpack = *unpack;
1245 if (scissoredUnpack.RowLength == 0)
1246 scissoredUnpack.RowLength = width;
1247
1248 /* clip left */
1249 if (x < ctx->Scissor.X) {
1250 scissoredUnpack.SkipPixels += (ctx->Scissor.X - x);
1251 width -= (ctx->Scissor.X - x);
1252 x = ctx->Scissor.X;
1253 }
1254 /* clip right */
1255 if (x + width >= ctx->Scissor.X + ctx->Scissor.Width) {
1256 width -= (x + width - (ctx->Scissor.X + ctx->Scissor.Width));
1257 }
1258 /* clip bottom */
1259 if (y < ctx->Scissor.Y) {
1260 scissoredUnpack.SkipRows += (ctx->Scissor.Y - y);
1261 height -= (ctx->Scissor.Y - y);
1262 y = ctx->Scissor.Y;
1263 }
1264 /* clip top */
1265 if (y + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
1266 height -= (y + height - (ctx->Scissor.Y + ctx->Scissor.Height));
1267 }
1268
1269 if (width <= 0 || height <= 0)
1270 return;
1271 }
1272 else {
1273 finalUnpack = unpack;
1274 }
1275
1276 info.size = sizeof(info);
1277 if (!grLfbLock(GR_LFB_WRITE_ONLY,
1278 fxMesa->currentFB,
1279 GR_LFBWRITEMODE_565,
1280 GR_ORIGIN_LOWER_LEFT, FXTRUE, &info)) {
1281 _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
1282 return;
1283 }
1284
1285 {
1286 const GLint winX = 0;
1287 const GLint winY = 0;
1288
1289 const GLint dstStride = info.strideInBytes / 2; /* stride in GLushorts */
1290 GLushort *dst = (GLushort *) info.lfbPtr + (winY + y) * dstStride + (winX + x);
1291
1292 if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
1293 GLint row;
1294 for (row = 0; row < height; row++) {
1295 GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
1296 width, height, format,
1297 type, 0, row, 0);
1298 GLint col;
1299 for (col = 0; col < width; col++) {
1300 dst[col] = TDFXPACKCOLOR565(src[2], src[1], src[0]);
1301 src += 4;
1302 }
1303 dst += dstStride;
1304 }
1305 }
1306 else if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
1307 GLint row;
1308 for (row = 0; row < height; row++) {
1309 GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
1310 width, height, format,
1311 type, 0, row, 0);
1312 GLint col;
1313 for (col = 0; col < width; col++) {
1314 dst[col] = TDFXPACKCOLOR565(src[2], src[1], src[0]);
1315 src += 3;
1316 }
1317 dst += dstStride;
1318 }
1319 }
1320 else {
1321 grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
1322 _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
1323 return;
1324 }
1325
1326 }
1327
1328 grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
1329 }
1330
1331
1332 void
1333 fxDDDrawPixels565_rev (GLcontext * ctx, GLint x, GLint y,
1334 GLsizei width, GLsizei height,
1335 GLenum format, GLenum type,
1336 const struct gl_pixelstore_attrib *unpack,
1337 const GLvoid * pixels)
1338 {
1339 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1340 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1341 GrLfbInfo_t info;
1342 const struct gl_pixelstore_attrib *finalUnpack;
1343 struct gl_pixelstore_attrib scissoredUnpack;
1344
1345 if (ctx->Pixel.ZoomX != 1.0F ||
1346 ctx->Pixel.ZoomY != 1.0F ||
1347 (ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
1348 IMAGE_MAP_COLOR_BIT)) ||
1349 (swrast->_RasterMask & (ALPHATEST_BIT |
1350 /*BLEND_BIT |*/ /* blending ok, through pixpipe */
1351 DEPTH_BIT | /* could be done with RGB:DEPTH */
1352 FOG_BIT | /* could be done with RGB:DEPTH */
1353 LOGIC_OP_BIT |
1354 /*CLIP_BIT |*/ /* clipping ok, below */
1355 STENCIL_BIT |
1356 MASKING_BIT |
1357 ALPHABUF_BIT |
1358 MULTI_DRAW_BIT |
1359 OCCLUSION_BIT | /* nope! at least not yet */
1360 TEXTURE_BIT |
1361 FRAGPROG_BIT)) ||
1362 fxMesa->fallback)
1363 {
1364 _swrast_DrawPixels( ctx, x, y, width, height, format, type,
1365 unpack, pixels );
1366 return;
1367 }
1368
1369 /* make sure the pixelpipe is configured correctly */
1370 fxSetupFXUnits(ctx);
1371
1372 /* FIXME! _RasterMask & CLIP_BIT gets set if we're out of Viewport, also! */
1373 if (ctx->Scissor.Enabled) {
1374 /* This is a bit tricky, but by carefully adjusting the px, py,
1375 * width, height, skipPixels and skipRows values we can do
1376 * scissoring without special code in the rendering loop.
1377 */
1378
1379 /* we'll construct a new pixelstore struct */
1380 finalUnpack = &scissoredUnpack;
1381 scissoredUnpack = *unpack;
1382 if (scissoredUnpack.RowLength == 0)
1383 scissoredUnpack.RowLength = width;
1384
1385 /* clip left */
1386 if (x < ctx->Scissor.X) {
1387 scissoredUnpack.SkipPixels += (ctx->Scissor.X - x);
1388 width -= (ctx->Scissor.X - x);
1389 x = ctx->Scissor.X;
1390 }
1391 /* clip right */
1392 if (x + width >= ctx->Scissor.X + ctx->Scissor.Width) {
1393 width -= (x + width - (ctx->Scissor.X + ctx->Scissor.Width));
1394 }
1395 /* clip bottom */
1396 if (y < ctx->Scissor.Y) {
1397 scissoredUnpack.SkipRows += (ctx->Scissor.Y - y);
1398 height -= (ctx->Scissor.Y - y);
1399 y = ctx->Scissor.Y;
1400 }
1401 /* clip top */
1402 if (y + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
1403 height -= (y + height - (ctx->Scissor.Y + ctx->Scissor.Height));
1404 }
1405
1406 if (width <= 0 || height <= 0)
1407 return;
1408 }
1409 else {
1410 finalUnpack = unpack;
1411 }
1412
1413 info.size = sizeof(info);
1414 if (!grLfbLock(GR_LFB_WRITE_ONLY,
1415 fxMesa->currentFB,
1416 GR_LFBWRITEMODE_565,
1417 GR_ORIGIN_LOWER_LEFT, FXTRUE, &info)) {
1418 _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
1419 return;
1420 }
1421
1422 {
1423 const GLint winX = 0;
1424 const GLint winY = 0;
1425
1426 const GLint dstStride = info.strideInBytes / 2; /* stride in GLushorts */
1427 GLushort *dst = (GLushort *) info.lfbPtr + (winY + y) * dstStride + (winX + x);
1428
1429 if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
1430 GLint row;
1431 for (row = 0; row < height; row++) {
1432 GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
1433 width, height, format,
1434 type, 0, row, 0);
1435 GLint col;
1436 for (col = 0; col < width; col++) {
1437 dst[col] = TDFXPACKCOLOR565(src[0], src[1], src[2]);
1438 src += 4;
1439 }
1440 dst += dstStride;
1441 }
1442 }
1443 else if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
1444 GLint row;
1445 for (row = 0; row < height; row++) {
1446 GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
1447 width, height, format,
1448 type, 0, row, 0);
1449 GLint col;
1450 for (col = 0; col < width; col++) {
1451 dst[col] = TDFXPACKCOLOR565(src[0], src[1], src[2]);
1452 src += 3;
1453 }
1454 dst += dstStride;
1455 }
1456 }
1457 else {
1458 grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
1459 _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
1460 return;
1461 }
1462
1463 }
1464
1465 grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
1466 }
1467
1468
1469 void
1470 fxDDDrawPixels8888 (GLcontext * ctx, GLint x, GLint y,
1471 GLsizei width, GLsizei height,
1472 GLenum format, GLenum type,
1473 const struct gl_pixelstore_attrib *unpack,
1474 const GLvoid * pixels)
1475 {
1476 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1477 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1478 GrLfbInfo_t info;
1479 const struct gl_pixelstore_attrib *finalUnpack;
1480 struct gl_pixelstore_attrib scissoredUnpack;
1481
1482 if (ctx->Pixel.ZoomX != 1.0F ||
1483 ctx->Pixel.ZoomY != 1.0F ||
1484 (ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
1485 IMAGE_MAP_COLOR_BIT)) ||
1486 (swrast->_RasterMask & (/*ALPHATEST_BIT |*/
1487 /*BLEND_BIT |*/ /* blending ok, through pixpipe */
1488 DEPTH_BIT | /* could be done with RGB:DEPTH */
1489 FOG_BIT | /* could be done with RGB:DEPTH */
1490 LOGIC_OP_BIT |
1491 /*CLIP_BIT |*/ /* clipping ok, below */
1492 STENCIL_BIT |
1493 /*MASKING_BIT |*/ /* masking ok, we're in 32bpp */
1494 /*ALPHABUF_BIT |*//* alpha ok, we're in 32bpp */
1495 MULTI_DRAW_BIT |
1496 OCCLUSION_BIT | /* nope! at least not yet */
1497 TEXTURE_BIT |
1498 FRAGPROG_BIT)) ||
1499 fxMesa->fallback)
1500 {
1501 _swrast_DrawPixels( ctx, x, y, width, height, format, type,
1502 unpack, pixels );
1503 return;
1504 }
1505
1506 /* make sure the pixelpipe is configured correctly */
1507 fxSetupFXUnits(ctx);
1508
1509 /* FIXME! _RasterMask & CLIP_BIT gets set if we're out of Viewport, also! */
1510 if (ctx->Scissor.Enabled) {
1511 /* This is a bit tricky, but by carefully adjusting the px, py,
1512 * width, height, skipPixels and skipRows values we can do
1513 * scissoring without special code in the rendering loop.
1514 */
1515
1516 /* we'll construct a new pixelstore struct */
1517 finalUnpack = &scissoredUnpack;
1518 scissoredUnpack = *unpack;
1519 if (scissoredUnpack.RowLength == 0)
1520 scissoredUnpack.RowLength = width;
1521
1522 /* clip left */
1523 if (x < ctx->Scissor.X) {
1524 scissoredUnpack.SkipPixels += (ctx->Scissor.X - x);
1525 width -= (ctx->Scissor.X - x);
1526 x = ctx->Scissor.X;
1527 }
1528 /* clip right */
1529 if (x + width >= ctx->Scissor.X + ctx->Scissor.Width) {
1530 width -= (x + width - (ctx->Scissor.X + ctx->Scissor.Width));
1531 }
1532 /* clip bottom */
1533 if (y < ctx->Scissor.Y) {
1534 scissoredUnpack.SkipRows += (ctx->Scissor.Y - y);
1535 height -= (ctx->Scissor.Y - y);
1536 y = ctx->Scissor.Y;
1537 }
1538 /* clip top */
1539 if (y + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
1540 height -= (y + height - (ctx->Scissor.Y + ctx->Scissor.Height));
1541 }
1542
1543 if (width <= 0 || height <= 0)
1544 return;
1545 }
1546 else {
1547 finalUnpack = unpack;
1548 }
1549
1550 info.size = sizeof(info);
1551 if (!grLfbLock(GR_LFB_WRITE_ONLY,
1552 fxMesa->currentFB,
1553 GR_LFBWRITEMODE_8888,
1554 GR_ORIGIN_LOWER_LEFT, FXTRUE, &info)) {
1555 _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
1556 return;
1557 }
1558
1559 {
1560 const GLint winX = 0;
1561 const GLint winY = 0;
1562
1563 const GLint dstStride = info.strideInBytes / 4; /* stride in GLuints */
1564 GLuint *dst = (GLuint *) info.lfbPtr + (winY + y) * dstStride + (winX + x);
1565
1566 if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
1567 /* directly memcpy 8A8R8G8B pixels to screen */
1568 const GLint widthInBytes = width * 4;
1569 GLint row;
1570 for (row = 0; row < height; row++) {
1571 GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
1572 width, height, format,
1573 type, 0, row, 0);
1574 MEMCPY(dst, src, widthInBytes);
1575 dst += dstStride;
1576 }
1577 }
1578 else if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
1579 GLint row;
1580 for (row = 0; row < height; row++) {
1581 GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
1582 width, height, format,
1583 type, 0, row, 0);
1584 GLint col;
1585 for (col = 0; col < width; col++) {
1586 dst[col] = TDFXPACKCOLOR8888(src[2], src[1], src[0], 255);
1587 src += 3;
1588 }
1589 dst += dstStride;
1590 }
1591 }
1592 else {
1593 grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
1594 _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
1595 return;
1596 }
1597
1598 }
1599
1600 grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
1601 }
1602
1603
1604 static void
1605 fxDDFinish(GLcontext * ctx)
1606 {
1607 grFlush();
1608 }
1609
1610
1611
1612
1613
1614 /* KW: Put the word Mesa in the render string because quakeworld
1615 * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE).
1616 * Why?
1617 */
1618 static const GLubyte *
1619 fxDDGetString(GLcontext * ctx, GLenum name)
1620 {
1621 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1622
1623 switch (name) {
1624 case GL_RENDERER:
1625 return (GLubyte *)fxMesa->rendererString;
1626 #if __WIN32__ /* hack to advertise vanilla extension names */
1627 case GL_EXTENSIONS:
1628 if (ctx->Extensions.String == NULL) {
1629 GLubyte *ext = _mesa_make_extension_string(ctx);
1630 if (ext != NULL) {
1631 ctx->Extensions.String = _mesa_malloc(strlen((char *)ext) + 256);
1632 if (ctx->Extensions.String != NULL) {
1633 strcpy((char *)ctx->Extensions.String, (char *)ext);
1634 /* put any additional extension names here */
1635 #if 0
1636 strcat((char *)ctx->Extensions.String, " 3DFX_set_global_palette");
1637 #endif
1638 #if __WIN32__
1639 strcat((char *)ctx->Extensions.String, " WGL_3DFX_gamma_control");
1640 strcat((char *)ctx->Extensions.String, " WGL_EXT_swap_control");
1641 strcat((char *)ctx->Extensions.String, " WGL_EXT_extensions_string WGL_ARB_extensions_string");
1642 #endif
1643 /* put any additional extension names here */
1644 _mesa_free(ext);
1645 } else {
1646 ctx->Extensions.String = ext;
1647 }
1648 }
1649 }
1650 return ctx->Extensions.String;
1651 #endif
1652 default:
1653 return NULL;
1654 }
1655 }
1656
1657 static const struct tnl_pipeline_stage *fx_pipeline[] = {
1658 &_tnl_vertex_transform_stage, /* XXX todo - Add the fastpath here */
1659 &_tnl_normal_transform_stage,
1660 &_tnl_lighting_stage,
1661 &_tnl_fog_coordinate_stage,
1662 &_tnl_texgen_stage,
1663 &_tnl_texture_transform_stage,
1664 &_tnl_point_attenuation_stage,
1665 #if defined(FEATURE_NV_vertex_program) || defined(FEATURE_ARB_vertex_program)
1666 &_tnl_vertex_program_stage,
1667 #endif
1668 &_tnl_render_stage,
1669 0,
1670 };
1671
1672
1673
1674
1675 int
1676 fxDDInitFxMesaContext(fxMesaContext fxMesa)
1677 {
1678 int i;
1679 GLcontext *ctx = fxMesa->glCtx;
1680
1681 FX_setupGrVertexLayout();
1682
1683 fxMesa->color = 0xffffffff;
1684 fxMesa->clearC = 0;
1685 fxMesa->clearA = 0;
1686
1687 fxMesa->stats.swapBuffer = 0;
1688 fxMesa->stats.reqTexUpload = 0;
1689 fxMesa->stats.texUpload = 0;
1690 fxMesa->stats.memTexUpload = 0;
1691
1692 fxMesa->tmuSrc = FX_TMU_NONE;
1693 fxMesa->lastUnitsMode = FX_UM_NONE;
1694 fxTMInit(fxMesa);
1695
1696 /* FX units setup */
1697
1698 fxMesa->unitsState.alphaTestEnabled = GL_FALSE;
1699 fxMesa->unitsState.alphaTestFunc = GL_ALWAYS;
1700 fxMesa->unitsState.alphaTestRefValue = 0.0;
1701
1702 fxMesa->unitsState.blendEnabled = GL_FALSE;
1703 fxMesa->unitsState.blendSrcFuncRGB = GR_BLEND_ONE;
1704 fxMesa->unitsState.blendDstFuncRGB = GR_BLEND_ZERO;
1705 fxMesa->unitsState.blendSrcFuncAlpha = GR_BLEND_ONE;
1706 fxMesa->unitsState.blendDstFuncAlpha = GR_BLEND_ZERO;
1707 fxMesa->unitsState.blendEqRGB = GR_BLEND_OP_ADD;
1708 fxMesa->unitsState.blendEqAlpha = GR_BLEND_OP_ADD;
1709
1710 fxMesa->unitsState.depthTestEnabled = GL_FALSE;
1711 fxMesa->unitsState.depthMask = GL_TRUE;
1712 fxMesa->unitsState.depthTestFunc = GL_LESS;
1713 fxMesa->unitsState.depthBias = 0;
1714
1715 fxMesa->unitsState.stencilWriteMask = 0xff;
1716
1717 if (fxMesa->colDepth == 32) {
1718 /* 32bpp */
1719 fxMesa->Glide.grColorMaskExt(FXTRUE, FXTRUE, FXTRUE, fxMesa->haveHwAlpha);
1720 } else {
1721 /* 15/16 bpp mode */
1722 grColorMask(FXTRUE, fxMesa->haveHwAlpha);
1723 }
1724
1725 fxMesa->currentFB = fxMesa->haveDoubleBuffer ? GR_BUFFER_BACKBUFFER : GR_BUFFER_FRONTBUFFER;
1726 grRenderBuffer(fxMesa->currentFB);
1727
1728 fxMesa->state = MALLOC(FX_grGetInteger(GR_GLIDE_STATE_SIZE));
1729 fxMesa->fogTable = (GrFog_t *) MALLOC(FX_grGetInteger(GR_FOG_TABLE_ENTRIES) *
1730 sizeof(GrFog_t));
1731
1732 if (!fxMesa->state || !fxMesa->fogTable) {
1733 if (fxMesa->state)
1734 FREE(fxMesa->state);
1735 if (fxMesa->fogTable)
1736 FREE(fxMesa->fogTable);
1737 return 0;
1738 }
1739
1740 if (fxMesa->haveZBuffer) {
1741 grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER);
1742 }
1743
1744 if (!fxMesa->bgrOrder) {
1745 grLfbWriteColorFormat(GR_COLORFORMAT_ABGR);
1746 }
1747
1748 if (fxMesa->Glide.grSetNumPendingBuffers != NULL) {
1749 fxMesa->Glide.grSetNumPendingBuffers(fxMesa->maxPendingSwapBuffers);
1750 }
1751
1752 fxMesa->textureAlign = FX_grGetInteger(GR_TEXTURE_ALIGN);
1753 /* [koolsmoky] */
1754 {
1755 char *env;
1756 int textureLevels = 0;
1757 int textureSize = FX_grGetInteger(GR_MAX_TEXTURE_SIZE);
1758 do {
1759 textureLevels++;
1760 } while ((textureSize >>= 0x1) & 0x7ff);
1761 ctx->Const.MaxTextureLevels = textureLevels;
1762 ctx->Const.MaxTextureLodBias = /*textureLevels - 1*/8; /* Glide bug */
1763 #if FX_RESCALE_BIG_TEXURES_HACK
1764 fxMesa->textureMaxLod = textureLevels - 1;
1765 if ((env = getenv("MESA_FX_MAXLOD")) != NULL) {
1766 int maxLevels = atoi(env) + 1;
1767 if ((maxLevels <= MAX_TEXTURE_LEVELS) && (maxLevels > textureLevels)) {
1768 ctx->Const.MaxTextureLevels = maxLevels;
1769 }
1770 }
1771 #endif
1772 }
1773 ctx->Const.MaxTextureCoordUnits =
1774 ctx->Const.MaxTextureImageUnits = fxMesa->haveTwoTMUs ? 2 : 1;
1775 ctx->Const.MaxTextureUnits = MAX2(ctx->Const.MaxTextureImageUnits, ctx->Const.MaxTextureCoordUnits);
1776
1777 fxMesa->new_state = _NEW_ALL;
1778 if (!fxMesa->haveHwStencil) {
1779 /* don't touch stencil if there is none */
1780 fxMesa->new_state &= ~FX_NEW_STENCIL;
1781 }
1782
1783 /* Initialize the software rasterizer and helper modules.
1784 */
1785 _swrast_CreateContext(ctx);
1786 _ac_CreateContext(ctx);
1787 _tnl_CreateContext(ctx);
1788 _swsetup_CreateContext(ctx);
1789
1790 /* Install customized pipeline */
1791 _tnl_destroy_pipeline(ctx);
1792 _tnl_install_pipeline(ctx, fx_pipeline);
1793
1794 fxAllocVB(ctx);
1795
1796 fxSetupDDPointers(ctx);
1797 fxDDInitTriFuncs(ctx);
1798
1799 /* Tell the software rasterizer to use pixel fog always.
1800 */
1801 _swrast_allow_vertex_fog(ctx, GL_FALSE);
1802 _swrast_allow_pixel_fog(ctx, GL_TRUE);
1803 _tnl_allow_vertex_fog( ctx, GL_FALSE );
1804 _tnl_allow_pixel_fog( ctx, GL_TRUE );
1805
1806 /* Tell tnl not to calculate or use vertex fog factors. (Needed to
1807 * tell render stage not to clip fog coords).
1808 */
1809 /* _tnl_calculate_vertex_fog( ctx, GL_FALSE ); */
1810
1811 fxDDInitExtensions(ctx);
1812
1813 #if 0
1814 /* do we want dither? It just looks bad... */
1815 grEnable(GR_ALLOW_MIPMAP_DITHER);
1816 #endif
1817 grGlideGetState((GrState *) fxMesa->state);
1818
1819 return 1;
1820 }
1821
1822 /* Undo the above.
1823 */
1824 void
1825 fxDDDestroyFxMesaContext(fxMesaContext fxMesa)
1826 {
1827 _swsetup_DestroyContext(fxMesa->glCtx);
1828 _tnl_DestroyContext(fxMesa->glCtx);
1829 _ac_DestroyContext(fxMesa->glCtx);
1830 _swrast_DestroyContext(fxMesa->glCtx);
1831
1832 if (fxMesa->state)
1833 FREE(fxMesa->state);
1834 if (fxMesa->fogTable)
1835 FREE(fxMesa->fogTable);
1836 fxFreeVB(fxMesa->glCtx);
1837 }
1838
1839
1840
1841
1842 void
1843 fxDDInitExtensions(GLcontext * ctx)
1844 {
1845 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1846
1847 #if 1 /* multipass ColorSum stage */
1848 _mesa_enable_extension(ctx, "GL_EXT_secondary_color");
1849 #endif
1850
1851 _mesa_enable_extension(ctx, "GL_ARB_point_sprite");
1852 _mesa_enable_extension(ctx, "GL_EXT_point_parameters");
1853 _mesa_enable_extension(ctx, "GL_EXT_paletted_texture");
1854 _mesa_enable_extension(ctx, "GL_EXT_texture_lod_bias");
1855 _mesa_enable_extension(ctx, "GL_EXT_shared_texture_palette");
1856 _mesa_enable_extension(ctx, "GL_EXT_blend_func_separate");
1857 _mesa_enable_extension(ctx, "GL_EXT_texture_env_add");
1858 _mesa_enable_extension(ctx, "GL_EXT_stencil_wrap");
1859
1860 if (fxMesa->haveTwoTMUs) {
1861 _mesa_enable_extension(ctx, "GL_ARB_multitexture");
1862 }
1863
1864 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
1865 _mesa_enable_extension(ctx, "GL_ARB_texture_compression");
1866 _mesa_enable_extension(ctx, "GL_3DFX_texture_compression_FXT1");
1867 _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
1868 _mesa_enable_extension(ctx, "GL_S3_s3tc");
1869 _mesa_enable_extension(ctx, "GL_NV_blend_square");
1870 } else {
1871 #if FX_TC_NCC
1872 /* [dBorca] Hack alert:
1873 * 1) NCC w/o DITHER_ERR has poor quality and NCC w/ DITHER_ERR is
1874 * damn slow!
1875 * 2) NCC compression cannot be used with multitexturing, because
1876 * the decompression tables are not per TMU anymore (bear in mind
1877 * that earlier Voodoos could handle 2 NCC tables for each TMU --
1878 * just look for POINTCAST_PALETTE). As a last resort, we could
1879 * fake NCC multitexturing through multipass rendering, but...
1880 * ohwell, it's not worth the effort...
1881 * This stand true for multitexturing palletized textures.
1882 * 3) since NCC is not an OpenGL standard (as opposed to FXT1/DXTC), we
1883 * can't use precompressed textures!
1884 */
1885 if (fxMesa->HaveTexus2) {
1886 _mesa_enable_extension(ctx, "GL_ARB_texture_compression");
1887 }
1888 #else
1889 /* doesn't like texture compression */
1890 _mesa_enable_extension(ctx, "GL_SGIS_generate_mipmap");
1891 #endif
1892 }
1893
1894 if (fxMesa->HaveCmbExt) {
1895 _mesa_enable_extension(ctx, "GL_ARB_texture_env_combine");
1896 _mesa_enable_extension(ctx, "GL_EXT_texture_env_combine");
1897 }
1898
1899 if (fxMesa->HavePixExt) {
1900 _mesa_enable_extension(ctx, "GL_EXT_blend_subtract");
1901 _mesa_enable_extension(ctx, "GL_EXT_blend_equation_separate");
1902 }
1903
1904 if (fxMesa->HaveMirExt) {
1905 _mesa_enable_extension(ctx, "GL_ARB_texture_mirrored_repeat");
1906 }
1907
1908 if (fxMesa->type >= GR_SSTTYPE_Voodoo2) {
1909 _mesa_enable_extension(ctx, "GL_EXT_fog_coord");
1910 }
1911
1912 /* core-level extensions */
1913 _mesa_enable_extension(ctx, "GL_EXT_multi_draw_arrays");
1914 _mesa_enable_extension(ctx, "GL_IBM_multimode_draw_arrays");
1915 _mesa_enable_extension(ctx, "GL_ARB_vertex_buffer_object");
1916 #if 1
1917 /* not just yet */
1918 _mesa_enable_extension(ctx, "GL_ARB_vertex_program");
1919 _mesa_enable_extension(ctx, "GL_NV_vertex_program");
1920 _mesa_enable_extension(ctx, "GL_NV_vertex_program1_1");
1921 _mesa_enable_extension(ctx, "GL_MESA_program_debug");
1922 #endif
1923 }
1924
1925
1926 /************************************************************************/
1927 /************************************************************************/
1928 /************************************************************************/
1929
1930 /* Check if the hardware supports the current context
1931 *
1932 * Performs similar work to fxDDChooseRenderState() - should be merged.
1933 */
1934 GLuint
1935 fx_check_IsInHardware(GLcontext * ctx)
1936 {
1937 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1938
1939 if (ctx->RenderMode != GL_RENDER) {
1940 return FX_FALLBACK_RENDER_MODE;
1941 }
1942
1943 if (ctx->Stencil.Enabled && !fxMesa->haveHwStencil) {
1944 return FX_FALLBACK_STENCIL;
1945 }
1946
1947 if (ctx->Color._DrawDestMask != DD_FRONT_LEFT_BIT &&
1948 ctx->Color._DrawDestMask != DD_BACK_LEFT_BIT) {
1949 return FX_FALLBACK_DRAW_BUFFER;
1950 }
1951
1952 if (ctx->Color.BlendEnabled) {
1953 if (ctx->Color.BlendEquationRGB != GL_FUNC_ADD) {
1954 if (!fxMesa->HavePixExt ||
1955 ((ctx->Color.BlendEquationRGB != GL_FUNC_SUBTRACT) &&
1956 (ctx->Color.BlendEquationRGB != GL_FUNC_REVERSE_SUBTRACT))) {
1957 return FX_FALLBACK_BLEND;
1958 }
1959 }
1960
1961 if (ctx->Color.BlendEquationA != GL_FUNC_ADD) {
1962 if (!fxMesa->HavePixExt ||
1963 ((ctx->Color.BlendEquationA != GL_FUNC_SUBTRACT) &&
1964 (ctx->Color.BlendEquationA != GL_FUNC_REVERSE_SUBTRACT))) {
1965 return FX_FALLBACK_BLEND;
1966 }
1967 }
1968
1969 #if 0
1970 /* [dBorca]
1971 * We fail the spec here, unless certain blending modes:
1972 * RGB: (GL_ONE + GL_*) or (GL_ZERO + GL_*) or ...
1973 */
1974 if (NEED_SECONDARY_COLOR(ctx)) {
1975 if ((ctx->Color.BlendEquationRGB != GL_FUNC_ADD) &&
1976 (ctx->Color.BlendSrcRGB != GL_ONE)) {
1977 /* Can't use multipass to blend ColorSum stage */
1978 return FX_FALLBACK_SPECULAR;
1979 }
1980 }
1981 #endif
1982 }
1983
1984 /* [dBorca]
1985 * We could avoid this for certain `sfactor/dfactor'
1986 * I do not think that is even worthwhile to check
1987 * because if someone is using blending they use more
1988 * interesting settings and also it would add more
1989 * state tracking to a lot of the code.
1990 */
1991 if (ctx->Color.ColorLogicOpEnabled && (ctx->Color.LogicOp != GL_COPY)) {
1992 return FX_FALLBACK_LOGICOP;
1993 }
1994
1995 if ((fxMesa->colDepth != 32) &&
1996 ((ctx->Color.ColorMask[RCOMP] != ctx->Color.ColorMask[GCOMP]) ||
1997 (ctx->Color.ColorMask[GCOMP] != ctx->Color.ColorMask[BCOMP]))) {
1998 return FX_FALLBACK_COLORMASK;
1999 }
2000
2001 /* Unsupported texture/multitexture cases */
2002
2003 /* we can only do 1D/2D textures */
2004 if (ctx->Texture.Unit[0]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
2005 return FX_FALLBACK_TEXTURE_MAP;
2006
2007 if (fxMesa->haveTwoTMUs) {
2008 if (ctx->Texture.Unit[1]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
2009 return FX_FALLBACK_TEXTURE_MAP;
2010
2011 if (ctx->Texture.Unit[0]._ReallyEnabled) {
2012 if (fxMesa->type < GR_SSTTYPE_Voodoo2)
2013 if (ctx->Texture.Unit[0].EnvMode == GL_BLEND &&
2014 (ctx->Texture.Unit[1]._ReallyEnabled ||
2015 ctx->Texture.Unit[0].EnvColor[0] != 0 ||
2016 ctx->Texture.Unit[0].EnvColor[1] != 0 ||
2017 ctx->Texture.Unit[0].EnvColor[2] != 0 ||
2018 ctx->Texture.Unit[0].EnvColor[3] != 1)) {
2019 return FX_FALLBACK_TEXTURE_ENV;
2020 }
2021 if (ctx->Texture.Unit[0]._Current->Image[0][0]->Border > 0)
2022 return FX_FALLBACK_TEXTURE_BORDER;
2023 }
2024
2025 if (ctx->Texture.Unit[1]._ReallyEnabled) {
2026 if (fxMesa->type < GR_SSTTYPE_Voodoo2)
2027 if (ctx->Texture.Unit[1].EnvMode == GL_BLEND)
2028 return FX_FALLBACK_TEXTURE_ENV;
2029 if (ctx->Texture.Unit[1]._Current->Image[0][0]->Border > 0)
2030 return FX_FALLBACK_TEXTURE_BORDER;
2031 }
2032
2033 if (TDFX_DEBUG & (VERBOSE_DRIVER | VERBOSE_TEXTURE))
2034 fprintf(stderr, "fx_check_IsInHardware: envmode is %s/%s\n",
2035 _mesa_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode),
2036 _mesa_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode));
2037
2038 /* KW: This was wrong (I think) and I changed it... which doesn't mean
2039 * it is now correct...
2040 * BP: The old condition just seemed to test if both texture units
2041 * were enabled. That's easy!
2042 */
2043 if (ctx->Texture._EnabledUnits == 0x3) {
2044 #if 0
2045 /* Can't use multipass to blend a multitextured triangle - fall
2046 * back to software.
2047 */
2048 if (!fxMesa->haveTwoTMUs && ctx->Color.BlendEnabled) {
2049 return FX_FALLBACK_TEXTURE_MULTI;
2050 }
2051 #endif
2052
2053 if ((ctx->Texture.Unit[0].EnvMode != ctx->Texture.Unit[1].EnvMode) &&
2054 (ctx->Texture.Unit[0].EnvMode != GL_MODULATE) &&
2055 (ctx->Texture.Unit[0].EnvMode != GL_REPLACE)) { /* q2, seems ok... */
2056 if (TDFX_DEBUG & VERBOSE_DRIVER)
2057 fprintf(stderr, "fx_check_IsInHardware: unsupported multitex env mode\n");
2058 return FX_FALLBACK_TEXTURE_MULTI;
2059 }
2060 }
2061 }
2062 else {
2063 /* we have just one texture unit */
2064 if (ctx->Texture._EnabledUnits > 0x1) {
2065 return FX_FALLBACK_TEXTURE_MULTI;
2066 }
2067
2068 if (fxMesa->type < GR_SSTTYPE_Voodoo2)
2069 if (ctx->Texture.Unit[0]._ReallyEnabled &&
2070 (ctx->Texture.Unit[0].EnvMode == GL_BLEND)) {
2071 return FX_FALLBACK_TEXTURE_ENV;
2072 }
2073 }
2074
2075 return 0;
2076 }
2077
2078
2079
2080 static void
2081 fxDDUpdateDDPointers(GLcontext * ctx, GLuint new_state)
2082 {
2083 /* TNLcontext *tnl = TNL_CONTEXT(ctx);*/
2084 fxMesaContext fxMesa = FX_CONTEXT(ctx);
2085
2086 if (TDFX_DEBUG & VERBOSE_DRIVER) {
2087 fprintf(stderr, "fxDDUpdateDDPointers(%08x)\n", new_state);
2088 }
2089
2090 _swrast_InvalidateState(ctx, new_state);
2091 _ac_InvalidateState(ctx, new_state);
2092 _tnl_InvalidateState(ctx, new_state);
2093 _swsetup_InvalidateState(ctx, new_state);
2094
2095 fxMesa->new_gl_state |= new_state;
2096 }
2097
2098
2099
2100
2101 void
2102 fxSetupDDPointers(GLcontext * ctx)
2103 {
2104 fxMesaContext fxMesa = FX_CONTEXT(ctx);
2105 TNLcontext *tnl = TNL_CONTEXT(ctx);
2106
2107 if (TDFX_DEBUG & VERBOSE_DRIVER) {
2108 fprintf(stderr, "fxSetupDDPointers()\n");
2109 }
2110
2111 ctx->Driver.UpdateState = fxDDUpdateDDPointers;
2112 ctx->Driver.GetString = fxDDGetString;
2113 ctx->Driver.ClearIndex = NULL;
2114 ctx->Driver.ClearColor = fxDDClearColor;
2115 ctx->Driver.Clear = fxDDClear;
2116 ctx->Driver.DrawBuffer = fxDDSetDrawBuffer;
2117 ctx->Driver.GetBufferSize = fxDDBufferSize;
2118 switch (fxMesa->colDepth) {
2119 case 15:
2120 ctx->Driver.DrawPixels = fxDDDrawPixels555;
2121 ctx->Driver.ReadPixels = fxDDReadPixels555;
2122 ctx->Driver.Bitmap = fxDDDrawBitmap2;
2123 break;
2124 case 16:
2125 ctx->Driver.DrawPixels = !fxMesa->bgrOrder ? fxDDDrawPixels565 : fxDDDrawPixels565_rev;
2126 ctx->Driver.ReadPixels = fxDDReadPixels565;
2127 ctx->Driver.Bitmap = fxDDDrawBitmap2;
2128 break;
2129 case 32:
2130 ctx->Driver.DrawPixels = fxDDDrawPixels8888;
2131 ctx->Driver.ReadPixels = fxDDReadPixels8888;
2132 ctx->Driver.Bitmap = fxDDDrawBitmap4;
2133 break;
2134 }
2135 ctx->Driver.Finish = fxDDFinish;
2136 ctx->Driver.Flush = NULL;
2137 ctx->Driver.ChooseTextureFormat = fxDDChooseTextureFormat;
2138 ctx->Driver.TexImage1D = fxDDTexImage1D;
2139 ctx->Driver.TexImage2D = fxDDTexImage2D;
2140 ctx->Driver.TexSubImage1D = fxDDTexSubImage1D;
2141 ctx->Driver.TexSubImage2D = fxDDTexSubImage2D;
2142 ctx->Driver.CompressedTexImage2D = fxDDCompressedTexImage2D;
2143 ctx->Driver.CompressedTexSubImage2D = fxDDCompressedTexSubImage2D;
2144 ctx->Driver.TestProxyTexImage = fxDDTestProxyTexImage;
2145 ctx->Driver.TexEnv = fxDDTexEnv;
2146 ctx->Driver.TexParameter = fxDDTexParam;
2147 ctx->Driver.BindTexture = fxDDTexBind;
2148 ctx->Driver.DeleteTexture = fxDDTexDel;
2149 ctx->Driver.IsTextureResident = fxDDIsTextureResident;
2150 ctx->Driver.UpdateTexturePalette = fxDDTexPalette;
2151 ctx->Driver.AlphaFunc = fxDDAlphaFunc;
2152 ctx->Driver.BlendFuncSeparate = fxDDBlendFuncSeparate;
2153 ctx->Driver.BlendEquationSeparate = fxDDBlendEquationSeparate;
2154 ctx->Driver.DepthFunc = fxDDDepthFunc;
2155 ctx->Driver.DepthMask = fxDDDepthMask;
2156 ctx->Driver.ColorMask = fxDDColorMask;
2157 ctx->Driver.Fogfv = fxDDFogfv;
2158 ctx->Driver.Scissor = fxDDScissor;
2159 ctx->Driver.FrontFace = fxDDFrontFace;
2160 ctx->Driver.CullFace = fxDDCullFace;
2161 ctx->Driver.ShadeModel = fxDDShadeModel;
2162 ctx->Driver.Enable = fxDDEnable;
2163 if (fxMesa->haveHwStencil) {
2164 ctx->Driver.StencilFunc = fxDDStencilFunc;
2165 ctx->Driver.StencilMask = fxDDStencilMask;
2166 ctx->Driver.StencilOp = fxDDStencilOp;
2167 }
2168
2169 fxSetupDDSpanPointers(ctx);
2170 fxDDUpdateDDPointers(ctx, ~0);
2171 }
2172
2173
2174 #else
2175
2176
2177 /*
2178 * Need this to provide at least one external definition.
2179 */
2180
2181 extern int gl_fx_dummy_function_dd(void);
2182 int
2183 gl_fx_dummy_function_dd(void)
2184 {
2185 return 0;
2186 }
2187
2188 #endif /* FX */