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