draw: corrections to allow for different cliptest cases
[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
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(GLcontext * 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(GLcontext * 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(GLcontext * 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(GLcontext * 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(GLcontext * 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 }