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