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