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