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