Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / tdfx / tdfx_pixels.c
1 /* -*- mode: c; c-basic-offset: 3 -*-
2  *
3  * Copyright 2000 VA Linux Systems Inc., Fremont, California.
4  *
5  * 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 (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26
27 /*
28  * Original rewrite:
29  *      Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
30  *
31  * Authors:
32  *      Gareth Hughes <gareth@valinux.com>
33  *      Brian Paul <brianp@valinux.com>
34  *      Nathan Hand <nhand@valinux.com>
35  *
36  */
37
38 #include "tdfx_context.h"
39 #include "tdfx_dd.h"
40 #include "tdfx_lock.h"
41 #include "tdfx_pixels.h"
42 #include "tdfx_render.h"
43
44 #include "swrast/swrast.h"
45
46 #include "main/image.h"
47
48
49 #define FX_grLfbWriteRegion(fxMesa,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)          \
50   do {                          \
51     LOCK_HARDWARE(fxMesa);              \
52     fxMesa->Glide.grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,FXFALSE,src_stride,src_data); \
53     UNLOCK_HARDWARE(fxMesa);            \
54   } while(0)
55
56
57 #define FX_grLfbReadRegion(fxMesa,src_buffer,src_x,src_y,src_width,src_height,dst_stride,dst_data)                      \
58   do {                          \
59     LOCK_HARDWARE(fxMesa);              \
60     fxMesa->Glide.grLfbReadRegion(src_buffer,src_x,src_y,src_width,src_height,dst_stride,dst_data);                             \
61     UNLOCK_HARDWARE(fxMesa);            \
62   } while (0);
63
64
65 #if 0
66 static FxBool
67 FX_grLfbLock(tdfxContextPtr fxMesa, GrLock_t type, GrBuffer_t buffer,
68              GrLfbWriteMode_t writeMode, GrOriginLocation_t origin,
69              FxBool pixelPipeline, GrLfbInfo_t * info)
70 {
71    FxBool result;
72
73    LOCK_HARDWARE(fxMesa);
74    result = fxMesa->Glide.grLfbLock(type, buffer, writeMode, origin, pixelPipeline, info);
75    UNLOCK_HARDWARE(fxMesa);
76    return result;
77 }
78 #endif
79
80
81 #define FX_grLfbUnlock(fxMesa, t, b)    \
82   do {                                  \
83     LOCK_HARDWARE(fxMesa);              \
84     fxMesa->Glide.grLfbUnlock(t, b);    \
85     UNLOCK_HARDWARE(fxMesa);            \
86   } while (0)
87
88
89
90 #if 0
91 /* test if window coord (px,py) is visible */
92 static GLboolean
93 inClipRects(tdfxContextPtr fxMesa, int px, int py)
94 {
95     int i;
96     for (i = 0; i < fxMesa->numClipRects; i++) {
97         if ((px >= fxMesa->pClipRects[i].x1) &&
98             (px < fxMesa->pClipRects[i].x2) &&
99             (py >= fxMesa->pClipRects[i].y1) &&
100             (py < fxMesa->pClipRects[i].y2)) return GL_TRUE;
101     }
102     return GL_FALSE;
103 }
104 #endif
105
106 /* test if rectangle of pixels (px,py) (px+width,py+height) is visible */
107 static GLboolean
108 inClipRects_Region(tdfxContextPtr fxMesa, int x, int y, int width, int height)
109 {
110     int i;
111     int x1, y1, x2, y2;
112     int xmin, xmax, ymin, ymax, pixelsleft;
113
114     y1 = y - height + 1; y2 = y;
115     x1 = x; x2 = x + width - 1;
116     pixelsleft = width * height;
117
118     for (i = 0; i < fxMesa->numClipRects; i++)
119     {
120         /* algorithm requires x1 < x2 and y1 < y2 */
121         if ((fxMesa->pClipRects[i].x1 < fxMesa->pClipRects[i].x2)) {
122             xmin = fxMesa->pClipRects[i].x1;
123             xmax = fxMesa->pClipRects[i].x2-1;
124         } else {
125             xmin = fxMesa->pClipRects[i].x2;
126             xmax = fxMesa->pClipRects[i].x1-1;
127         }
128         if ((fxMesa->pClipRects[i].y1 < fxMesa->pClipRects[i].y2)) {
129             ymin = fxMesa->pClipRects[i].y1;
130             ymax = fxMesa->pClipRects[i].y2-1;
131         } else {
132             ymin = fxMesa->pClipRects[i].y2;
133             ymax = fxMesa->pClipRects[i].y1-1;
134         }
135
136         /* reject trivial cases */
137         if (xmax < x1) continue;
138         if (ymax < y1) continue;
139         if (xmin > x2) continue;
140         if (ymin > y2) continue;
141
142         /* find the intersection */
143         if (xmin < x1) xmin = x1;
144         if (ymin < y1) ymin = y1;
145         if (xmax > x2) xmax = x2;
146         if (ymax > y2) ymax = y2;
147
148         pixelsleft -= (xmax-xmin+1) * (ymax-ymin+1);
149     }
150
151     return pixelsleft == 0;
152 }
153
154 #if 0
155 GLboolean
156 tdfx_bitmap_R5G6B5(struct gl_context * ctx, GLint px, GLint py,
157                    GLsizei width, GLsizei height,
158                    const struct gl_pixelstore_attrib *unpack,
159                    const GLubyte * bitmap)
160 {
161    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
162    GrLfbInfo_t info;
163    TdfxU16 color;
164    const struct gl_pixelstore_attrib *finalUnpack;
165    struct gl_pixelstore_attrib scissoredUnpack;
166
167    /* check if there's any raster operations enabled which we can't handle */
168    if (ctx->RasterMask & (ALPHATEST_BIT |
169                           BLEND_BIT |
170                           DEPTH_BIT |
171                           FOG_BIT |
172                           LOGIC_OP_BIT |
173                           SCISSOR_BIT |
174                           STENCIL_BIT |
175                           MASKING_BIT |
176                           MULTI_DRAW_BIT)) return GL_FALSE;
177
178    if (ctx->Scissor.Enabled) {
179       /* This is a bit tricky, but by carefully adjusting the px, py,
180        * width, height, skipPixels and skipRows values we can do
181        * scissoring without special code in the rendering loop.
182        */
183
184       /* we'll construct a new pixelstore struct */
185       finalUnpack = &scissoredUnpack;
186       scissoredUnpack = *unpack;
187       if (scissoredUnpack.RowLength == 0)
188          scissoredUnpack.RowLength = width;
189
190       /* clip left */
191       if (px < ctx->Scissor.X) {
192          scissoredUnpack.SkipPixels += (ctx->Scissor.X - px);
193          width -= (ctx->Scissor.X - px);
194          px = ctx->Scissor.X;
195       }
196       /* clip right */
197       if (px + width >= ctx->Scissor.X + ctx->Scissor.Width) {
198          width -= (px + width - (ctx->Scissor.X + ctx->Scissor.Width));
199       }
200       /* clip bottom */
201       if (py < ctx->Scissor.Y) {
202          scissoredUnpack.SkipRows += (ctx->Scissor.Y - py);
203          height -= (ctx->Scissor.Y - py);
204          py = ctx->Scissor.Y;
205       }
206       /* clip top */
207       if (py + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
208          height -= (py + height - (ctx->Scissor.Y + ctx->Scissor.Height));
209       }
210
211       if (width <= 0 || height <= 0)
212          return GL_TRUE;     /* totally scissored away */
213    }
214    else {
215       finalUnpack = unpack;
216    }
217
218    /* compute pixel value */
219    {
220       GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0f);
221       GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0f);
222       GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0f);
223       /*GLint a = (GLint)(ctx->Current.RasterColor[3]*255.0f); */
224       if (fxMesa->bgrOrder) {
225          color = (TdfxU16)
226             (((TdfxU16) 0xf8 & b) << (11 - 3)) |
227             (((TdfxU16) 0xfc & g) << (5 - 3 + 1)) |
228             (((TdfxU16) 0xf8 & r) >> 3);
229       }
230       else
231          color = (TdfxU16)
232             (((TdfxU16) 0xf8 & r) << (11 - 3)) |
233             (((TdfxU16) 0xfc & g) << (5 - 3 + 1)) |
234             (((TdfxU16) 0xf8 & b) >> 3);
235    }
236
237    info.size = sizeof(info);
238    if (!TDFX_grLfbLock(fxMesa,
239                      GR_LFB_WRITE_ONLY,
240                      fxMesa->currentFB,
241                      GR_LFBWRITEMODE_565,
242                      GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
243 #ifndef TDFX_SILENT
244       fprintf(stderr, "tdfx Driver: error locking the linear frame buffer\n");
245 #endif
246       return GL_TRUE;
247    }
248
249    {
250       const GLint winX = fxMesa->x_offset;
251       const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
252       /* The dest stride depends on the hardware and whether we're drawing
253        * to the front or back buffer.  This compile-time test seems to do
254        * the job for now.
255        */
256       const GLint dstStride = (fxMesa->glCtx->Color.DrawBuffer[0] == GL_FRONT)
257          ? (fxMesa->screen_width) : (info.strideInBytes / 2);
258       GLint row;
259       /* compute dest address of bottom-left pixel in bitmap */
260       GLushort *dst = (GLushort *) info.lfbPtr
261          + (winY - py) * dstStride + (winX + px);
262
263       for (row = 0; row < height; row++) {
264          const GLubyte *src =
265             (const GLubyte *) _mesa_image_address2d(finalUnpack,
266                                                     bitmap, width, height,
267                                                     GL_COLOR_INDEX,
268                                                     GL_BITMAP, row, 0);
269          if (finalUnpack->LsbFirst) {
270             /* least significan bit first */
271             GLubyte mask = 1U << (finalUnpack->SkipPixels & 0x7);
272             GLint col;
273             for (col = 0; col < width; col++) {
274                if (*src & mask) {
275                   if (inClipRects(fxMesa, winX + px + col, winY - py - row))
276                      dst[col] = color;
277                }
278                if (mask == 128U) {
279                   src++;
280                   mask = 1U;
281                }
282                else {
283                   mask = mask << 1;
284                }
285             }
286             if (mask != 1)
287                src++;
288          }
289          else {
290             /* most significan bit first */
291             GLubyte mask = 128U >> (finalUnpack->SkipPixels & 0x7);
292             GLint col;
293             for (col = 0; col < width; col++) {
294                if (*src & mask) {
295                   if (inClipRects(fxMesa, winX + px + col, winY - py - row))
296                      dst[col] = color;
297                }
298                if (mask == 1U) {
299                   src++;
300                   mask = 128U;
301                }
302                else {
303                   mask = mask >> 1;
304                }
305             }
306             if (mask != 128)
307                src++;
308          }
309          dst -= dstStride;
310       }
311    }
312
313    TDFX_grLfbUnlock(fxMesa, GR_LFB_WRITE_ONLY, fxMesa->currentFB);
314    return GL_TRUE;
315 }
316 #endif
317
318 #if 0
319 GLboolean
320 tdfx_bitmap_R8G8B8A8(struct gl_context * ctx, GLint px, GLint py,
321                      GLsizei width, GLsizei height,
322                      const struct gl_pixelstore_attrib *unpack,
323                      const GLubyte * bitmap)
324 {
325    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
326    GrLfbInfo_t info;
327    GLuint color;
328    const struct gl_pixelstore_attrib *finalUnpack;
329    struct gl_pixelstore_attrib scissoredUnpack;
330
331    /* check if there's any raster operations enabled which we can't handle */
332    if (ctx->RasterMask & (ALPHATEST_BIT |
333                           BLEND_BIT |
334                           DEPTH_BIT |
335                           FOG_BIT |
336                           LOGIC_OP_BIT |
337                           SCISSOR_BIT |
338                           STENCIL_BIT |
339                           MASKING_BIT |
340                           MULTI_DRAW_BIT)) return GL_FALSE;
341
342    if (ctx->Scissor.Enabled) {
343       /* This is a bit tricky, but by carefully adjusting the px, py,
344        * width, height, skipPixels and skipRows values we can do
345        * scissoring without special code in the rendering loop.
346        */
347
348       /* we'll construct a new pixelstore struct */
349       finalUnpack = &scissoredUnpack;
350       scissoredUnpack = *unpack;
351       if (scissoredUnpack.RowLength == 0)
352          scissoredUnpack.RowLength = width;
353
354       /* clip left */
355       if (px < ctx->Scissor.X) {
356          scissoredUnpack.SkipPixels += (ctx->Scissor.X - px);
357          width -= (ctx->Scissor.X - px);
358          px = ctx->Scissor.X;
359       }
360       /* clip right */
361       if (px + width >= ctx->Scissor.X + ctx->Scissor.Width) {
362          width -= (px + width - (ctx->Scissor.X + ctx->Scissor.Width));
363       }
364       /* clip bottom */
365       if (py < ctx->Scissor.Y) {
366          scissoredUnpack.SkipRows += (ctx->Scissor.Y - py);
367          height -= (ctx->Scissor.Y - py);
368          py = ctx->Scissor.Y;
369       }
370       /* clip top */
371       if (py + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
372          height -= (py + height - (ctx->Scissor.Y + ctx->Scissor.Height));
373       }
374
375       if (width <= 0 || height <= 0)
376          return GL_TRUE;     /* totally scissored away */
377    }
378    else {
379       finalUnpack = unpack;
380    }
381
382    /* compute pixel value */
383    {
384       GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0f);
385       GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0f);
386       GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0f);
387       GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0f);
388       color = PACK_BGRA32(r, g, b, a);
389    }
390
391    info.size = sizeof(info);
392    if (!TDFX_grLfbLock(fxMesa, GR_LFB_WRITE_ONLY,
393                      fxMesa->currentFB, GR_LFBWRITEMODE_8888,
394                      GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
395 #ifndef TDFX_SILENT
396       fprintf(stderr, "tdfx Driver: error locking the linear frame buffer\n");
397 #endif
398       return GL_TRUE;
399    }
400
401    {
402       const GLint winX = fxMesa->x_offset;
403       const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
404       GLint dstStride;
405       GLuint *dst;
406       GLint row;
407
408       if (fxMesa->glCtx->Color.DrawBuffer[0] == GL_FRONT) {
409          dstStride = fxMesa->screen_width;
410          dst =
411             (GLuint *) info.lfbPtr + (winY - py) * dstStride + (winX +
412                                                                 px);
413       }
414       else {
415          dstStride = info.strideInBytes / 4;
416          dst =
417             (GLuint *) info.lfbPtr + (winY - py) * dstStride + (winX +
418                                                                 px);
419       }
420
421       /* compute dest address of bottom-left pixel in bitmap */
422       for (row = 0; row < height; row++) {
423          const GLubyte *src =
424             (const GLubyte *) _mesa_image_address2d(finalUnpack,
425                                                     bitmap, width, height,
426                                                     GL_COLOR_INDEX,
427                                                     GL_BITMAP, row, 0);
428          if (finalUnpack->LsbFirst) {
429             /* least significan bit first */
430             GLubyte mask = 1U << (finalUnpack->SkipPixels & 0x7);
431             GLint col;
432             for (col = 0; col < width; col++) {
433                if (*src & mask) {
434                   if (inClipRects(fxMesa, winX + px + col, winY - py - row))
435                      dst[col] = color;
436                }
437                if (mask == 128U) {
438                   src++;
439                   mask = 1U;
440                }
441                else {
442                   mask = mask << 1;
443                }
444             }
445             if (mask != 1)
446                src++;
447          }
448          else {
449             /* most significan bit first */
450             GLubyte mask = 128U >> (finalUnpack->SkipPixels & 0x7);
451             GLint col;
452             for (col = 0; col < width; col++) {
453                if (*src & mask) {
454                   if (inClipRects(fxMesa, winX + px + col, winY - py - row))
455                      dst[col] = color;
456                }
457                if (mask == 1U) {
458                   src++;
459                   mask = 128U;
460                }
461                else {
462                   mask = mask >> 1;
463                }
464             }
465             if (mask != 128)
466                src++;
467          }
468          dst -= dstStride;
469       }
470    }
471
472    TDFX_grLfbUnlock(fxMesa, GR_LFB_WRITE_ONLY, fxMesa->currentFB);
473    return GL_TRUE;
474 }
475 #endif
476
477 void
478 tdfx_readpixels_R5G6B5(struct gl_context * ctx, GLint x, GLint y,
479                        GLsizei width, GLsizei height,
480                        GLenum format, GLenum type,
481                        const struct gl_pixelstore_attrib *packing,
482                        GLvoid * dstImage)
483 {
484    if (format != GL_RGB ||
485        type != GL_UNSIGNED_SHORT_5_6_5 ||
486        (ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
487                                     IMAGE_MAP_COLOR_BIT)))
488    {
489       _swrast_ReadPixels( ctx, x, y, width, height, format, type, packing,
490                           dstImage );
491       return;
492    }
493
494    {
495       tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
496       GrLfbInfo_t info;
497       __DRIdrawable *const readable = fxMesa->driReadable;
498       const GLint winX = readable->x;
499       const GLint winY = readable->y + readable->h - 1;
500       const GLint scrX = winX + x;
501       const GLint scrY = winY - y;
502
503       LOCK_HARDWARE( fxMesa );
504       info.size = sizeof(info);
505       if (fxMesa->Glide.grLfbLock(GR_LFB_READ_ONLY,
506                     fxMesa->ReadBuffer,
507                     GR_LFBWRITEMODE_ANY,
508                     GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
509          const GLint srcStride = (fxMesa->glCtx->Color.DrawBuffer[0] ==
510              GL_FRONT) ? (fxMesa->screen_width) : (info.strideInBytes / 2);
511          const GLushort *src = (const GLushort *) info.lfbPtr
512             + scrY * srcStride + scrX;
513          GLubyte *dst = (GLubyte *) _mesa_image_address2d(packing,
514             dstImage, width, height, format, type, 0, 0);
515          const GLint dstStride = _mesa_image_row_stride(packing,
516             width, format, type);
517
518          /* directly memcpy 5R6G5B pixels into client's buffer */
519          const GLint widthInBytes = width * 2;
520          GLint row;
521          for (row = 0; row < height; row++) {
522             memcpy(dst, src, widthInBytes);
523             dst += dstStride;
524             src -= srcStride;
525          }
526
527          fxMesa->Glide.grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->ReadBuffer);
528       }
529       UNLOCK_HARDWARE( fxMesa );
530       return;
531    }
532 }
533
534 void
535 tdfx_readpixels_R8G8B8A8(struct gl_context * ctx, GLint x, GLint y,
536                          GLsizei width, GLsizei height,
537                          GLenum format, GLenum type,
538                          const struct gl_pixelstore_attrib *packing,
539                          GLvoid * dstImage)
540 {
541    if ((!(format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8) &&
542         !(format == GL_BGRA && type == GL_UNSIGNED_BYTE)) ||
543        (ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
544                                     IMAGE_MAP_COLOR_BIT)))
545    {
546       _swrast_ReadPixels( ctx, x, y, width, height, format, type, packing,
547                           dstImage );
548       return;
549    }
550
551
552    {
553       tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
554       GrLfbInfo_t info;
555       __DRIdrawable *const readable = fxMesa->driReadable;
556       const GLint winX = readable->x;
557       const GLint winY = readable->y + readable->h - 1;
558       const GLint scrX = winX + x;
559       const GLint scrY = winY - y;
560
561       LOCK_HARDWARE(fxMesa);
562       info.size = sizeof(info);
563       if (fxMesa->Glide.grLfbLock(GR_LFB_READ_ONLY,
564                     fxMesa->ReadBuffer,
565                     GR_LFBWRITEMODE_ANY,
566                     GR_ORIGIN_UPPER_LEFT, FXFALSE, &info))
567       {
568          const GLint srcStride = (fxMesa->glCtx->Color.DrawBuffer[0] == GL_FRONT)
569             ? (fxMesa->screen_width) : (info.strideInBytes / 4);
570          const GLuint *src = (const GLuint *) info.lfbPtr
571             + scrY * srcStride + scrX;
572          const GLint dstStride =
573             _mesa_image_row_stride(packing, width, format, type);
574          GLubyte *dst = (GLubyte *) _mesa_image_address2d(packing,
575             dstImage, width, height, format, type, 0, 0);
576          const GLint widthInBytes = width * 4;
577
578          {
579             GLint row;
580             for (row = 0; row < height; row++) {
581                memcpy(dst, src, widthInBytes);
582                dst += dstStride;
583                src -= srcStride;
584             }
585          }
586
587          fxMesa->Glide.grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->ReadBuffer);
588       }
589       UNLOCK_HARDWARE(fxMesa);
590    }
591 }
592
593 void
594 tdfx_drawpixels_R8G8B8A8(struct gl_context * ctx, GLint x, GLint y,
595                          GLsizei width, GLsizei height,
596                          GLenum format, GLenum type,
597                          const struct gl_pixelstore_attrib *unpack,
598                          const GLvoid * pixels)
599 {
600    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
601
602    if ((!(format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8) &&
603         !(format == GL_BGRA && type == GL_UNSIGNED_BYTE)) ||
604        ctx->Pixel.ZoomX != 1.0F || 
605        ctx->Pixel.ZoomY != 1.0F ||
606        (ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
607                                     IMAGE_MAP_COLOR_BIT)) ||
608        ctx->Color.AlphaEnabled ||
609        ctx->Depth.Test ||
610        ctx->Fog.Enabled ||
611        ctx->Scissor.Enabled ||
612        ctx->Stencil._Enabled ||
613        !ctx->Color.ColorMask[0][0] ||
614        !ctx->Color.ColorMask[0][1] ||
615        !ctx->Color.ColorMask[0][2] ||
616        !ctx->Color.ColorMask[0][3] ||
617        ctx->Color.ColorLogicOpEnabled ||
618        ctx->Texture._EnabledUnits ||
619        fxMesa->Fallback)       
620    {
621       _swrast_DrawPixels( ctx, x, y, width, height, format, type, 
622                           unpack, pixels );
623       return; 
624    }
625
626    {
627       tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
628       GrLfbInfo_t info;
629       GLboolean result = GL_FALSE;
630
631       const GLint winX = fxMesa->x_offset;
632       const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
633       const GLint scrX = winX + x;
634       const GLint scrY = winY - y;
635
636       /* lock early to make sure cliprects are right */
637       LOCK_HARDWARE(fxMesa);
638
639       /* make sure hardware has latest blend funcs */
640       if (ctx->Color.BlendEnabled) {
641          fxMesa->dirty |= TDFX_UPLOAD_BLEND_FUNC;
642          tdfxEmitHwStateLocked( fxMesa );
643       }
644
645       /* look for clipmasks, giveup if region obscured */
646       if (fxMesa->glCtx->Color.DrawBuffer[0] == GL_FRONT) {
647          if (!inClipRects_Region(fxMesa, scrX, scrY, width, height)) {
648             UNLOCK_HARDWARE(fxMesa);
649             _swrast_DrawPixels( ctx, x, y, width, height, format, type, 
650                                 unpack, pixels );
651             return;
652          }
653       }
654
655       info.size = sizeof(info);
656       if (fxMesa->Glide.grLfbLock(GR_LFB_WRITE_ONLY,
657                     fxMesa->DrawBuffer,
658                     GR_LFBWRITEMODE_8888,
659                     GR_ORIGIN_UPPER_LEFT, FXTRUE, &info))
660       {
661          const GLint dstStride = (fxMesa->glCtx->Color.DrawBuffer[0] == GL_FRONT)
662             ? (fxMesa->screen_width * 4) : (info.strideInBytes);
663          GLubyte *dst = (GLubyte *) info.lfbPtr
664             + scrY * dstStride + scrX * 4;
665          const GLint srcStride =
666             _mesa_image_row_stride(unpack, width, format, type);
667          const GLubyte *src = (GLubyte *) _mesa_image_address2d(unpack,
668             pixels, width, height, format, type, 0, 0);
669          const GLint widthInBytes = width * 4;
670
671          if ((format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8) ||
672              (format == GL_BGRA && type == GL_UNSIGNED_BYTE)) {
673             GLint row;
674             for (row = 0; row < height; row++) {
675                memcpy(dst, src, widthInBytes);
676                dst -= dstStride;
677                src += srcStride;
678             }
679             result = GL_TRUE;
680          }
681
682          fxMesa->Glide.grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->DrawBuffer);
683       }
684       UNLOCK_HARDWARE(fxMesa);
685    }
686 }