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