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