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