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