fixed a bunch of g++ warnings/errors. Compiling with g++ can help find lots of poten...
[mesa.git] / src / mesa / swrast / s_drawpix.c
1 /* $Id: s_drawpix.c,v 1.12 2001/03/07 05:06:12 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 #include "glheader.h"
29 #include "colormac.h"
30 #include "context.h"
31 #include "convolve.h"
32 #include "image.h"
33 #include "macros.h"
34 #include "mem.h"
35 #include "mmath.h"
36 #include "pixel.h"
37
38 #include "s_context.h"
39 #include "s_drawpix.h"
40 #include "s_pixeltex.h"
41 #include "s_span.h"
42 #include "s_stencil.h"
43 #include "s_texture.h"
44 #include "s_zoom.h"
45
46
47
48 /*
49 * Given the dest position, size and skipPixels and skipRows values
50 * for a glDrawPixels command, perform clipping of the image bounds
51 * so the result lies withing the context's buffer bounds.
52 * Return: GL_TRUE if image is ready for drawing
53 * GL_FALSE if image was completely clipped away (draw nothing)
54 */
55 GLboolean
56 _mesa_clip_pixelrect(const GLcontext *ctx,
57 GLint *destX, GLint *destY,
58 GLsizei *width, GLsizei *height,
59 GLint *skipPixels, GLint *skipRows)
60 {
61 const GLframebuffer *buffer = ctx->DrawBuffer;
62
63 /* left clipping */
64 if (*destX < buffer->_Xmin) {
65 *skipPixels += (buffer->_Xmin - *destX);
66 *width -= (buffer->_Xmin - *destX);
67 *destX = buffer->_Xmin;
68 }
69 /* right clipping */
70 if (*destX + *width > buffer->_Xmax)
71 *width -= (*destX + *width - buffer->_Xmax);
72
73 if (*width <= 0)
74 return GL_FALSE;
75
76 /* bottom clipping */
77 if (*destY < buffer->_Ymin) {
78 *skipRows += (buffer->_Ymin - *destY);
79 *height -= (buffer->_Ymin - *destY);
80 *destY = buffer->_Ymin;
81 }
82 /* top clipping */
83 if (*destY + *height > buffer->_Ymax)
84 *height -= (*destY + *height - buffer->_Ymax);
85
86 if (*height <= 0)
87 return GL_TRUE;
88
89 return GL_TRUE;
90 }
91
92
93
94 /*
95 * Try to do a fast and simple RGB(a) glDrawPixels.
96 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
97 */
98 static GLboolean
99 fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
100 GLsizei width, GLsizei height,
101 GLenum format, GLenum type, const GLvoid *pixels)
102 {
103 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
104 GLchan rgb[MAX_WIDTH][3];
105 GLchan rgba[MAX_WIDTH][4];
106
107 if (!ctx->Current.RasterPosValid) {
108 return GL_TRUE; /* no-op */
109 }
110
111 if ((SWRAST_CONTEXT(ctx)->_RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0
112 && ctx->Texture._ReallyEnabled == 0
113 && unpack->Alignment == 1
114 && !unpack->SwapBytes
115 && !unpack->LsbFirst) {
116
117 GLint destX = x;
118 GLint destY = y;
119 GLint drawWidth = width; /* actual width drawn */
120 GLint drawHeight = height; /* actual height drawn */
121 GLint skipPixels = unpack->SkipPixels;
122 GLint skipRows = unpack->SkipRows;
123 GLint rowLength;
124 GLdepth zSpan[MAX_WIDTH]; /* only used when zooming */
125 GLint zoomY0 = 0;
126
127 if (unpack->RowLength > 0)
128 rowLength = unpack->RowLength;
129 else
130 rowLength = width;
131
132 /* If we're not using pixel zoom then do all clipping calculations
133 * now. Otherwise, we'll let the _mesa_write_zoomed_*_span() functions
134 * handle the clipping.
135 */
136 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
137 /* horizontal clipping */
138 if (destX < ctx->DrawBuffer->_Xmin) {
139 skipPixels += (ctx->DrawBuffer->_Xmin - destX);
140 drawWidth -= (ctx->DrawBuffer->_Xmin - destX);
141 destX = ctx->DrawBuffer->_Xmin;
142 }
143 if (destX + drawWidth > ctx->DrawBuffer->_Xmax)
144 drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax);
145 if (drawWidth <= 0)
146 return GL_TRUE;
147
148 /* vertical clipping */
149 if (destY < ctx->DrawBuffer->_Ymin) {
150 skipRows += (ctx->DrawBuffer->_Ymin - destY);
151 drawHeight -= (ctx->DrawBuffer->_Ymin - destY);
152 destY = ctx->DrawBuffer->_Ymin;
153 }
154 if (destY + drawHeight > ctx->DrawBuffer->_Ymax)
155 drawHeight -= (destY + drawHeight - ctx->DrawBuffer->_Ymax);
156 if (drawHeight <= 0)
157 return GL_TRUE;
158 }
159 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
160 /* upside-down image */
161 /* horizontal clipping */
162 if (destX < ctx->DrawBuffer->_Xmin) {
163 skipPixels += (ctx->DrawBuffer->_Xmin - destX);
164 drawWidth -= (ctx->DrawBuffer->_Xmin - destX);
165 destX = ctx->DrawBuffer->_Xmin;
166 }
167 if (destX + drawWidth > ctx->DrawBuffer->_Xmax)
168 drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax);
169 if (drawWidth <= 0)
170 return GL_TRUE;
171
172 /* vertical clipping */
173 if (destY > ctx->DrawBuffer->_Ymax) {
174 skipRows += (destY - ctx->DrawBuffer->_Ymax);
175 drawHeight -= (destY - ctx->DrawBuffer->_Ymax);
176 destY = ctx->DrawBuffer->_Ymax;
177 }
178 if (destY - drawHeight < ctx->DrawBuffer->_Ymin)
179 drawHeight -= (ctx->DrawBuffer->_Ymin - (destY - drawHeight));
180 if (drawHeight <= 0)
181 return GL_TRUE;
182 }
183 else {
184 /* setup array of fragment Z value to pass to zoom function */
185 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->DepthMaxF);
186 GLint i;
187 ASSERT(drawWidth < MAX_WIDTH);
188 for (i=0; i<drawWidth; i++)
189 zSpan[i] = z;
190
191 /* save Y value of first row */
192 zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
193 }
194
195
196 /*
197 * Ready to draw!
198 * The window region at (destX, destY) of size (drawWidth, drawHeight)
199 * will be written to.
200 * We'll take pixel data from buffer pointed to by "pixels" but we'll
201 * skip "skipRows" rows and skip "skipPixels" pixels/row.
202 */
203
204 if (format == GL_RGBA && type == CHAN_TYPE
205 && ctx->_ImageTransferState==0) {
206 if (ctx->Visual.rgbMode) {
207 GLchan *src = (GLchan *) pixels
208 + (skipRows * rowLength + skipPixels) * 4;
209 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
210 /* no zooming */
211 GLint row;
212 for (row=0; row<drawHeight; row++) {
213 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
214 (CONST GLchan (*)[4]) src, NULL);
215 src += rowLength * 4;
216 destY++;
217 }
218 }
219 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
220 /* upside-down */
221 GLint row;
222 for (row=0; row<drawHeight; row++) {
223 destY--;
224 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
225 (CONST GLchan (*)[4]) src, NULL);
226 src += rowLength * 4;
227 }
228 }
229 else {
230 /* with zooming */
231 GLint row;
232 for (row=0; row<drawHeight; row++) {
233 _mesa_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
234 zSpan, 0, (CONST GLchan (*)[4]) src, zoomY0);
235 src += rowLength * 4;
236 destY++;
237 }
238 }
239 }
240 return GL_TRUE;
241 }
242 else if (format == GL_RGB && type == CHAN_TYPE
243 && ctx->_ImageTransferState == 0) {
244 if (ctx->Visual.rgbMode) {
245 GLchan *src = (GLchan *) pixels
246 + (skipRows * rowLength + skipPixels) * 3;
247 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
248 GLint row;
249 for (row=0; row<drawHeight; row++) {
250 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
251 (CONST GLchan (*)[3]) src, NULL);
252 src += rowLength * 3;
253 destY++;
254 }
255 }
256 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
257 /* upside-down */
258 GLint row;
259 for (row=0; row<drawHeight; row++) {
260 destY--;
261 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
262 (CONST GLchan (*)[3]) src, NULL);
263 src += rowLength * 3;
264 }
265 }
266 else {
267 /* with zooming */
268 GLint row;
269 for (row=0; row<drawHeight; row++) {
270 _mesa_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
271 zSpan, 0, (GLchan (*)[3]) src, zoomY0);
272 src += rowLength * 3;
273 destY++;
274 }
275 }
276 }
277 return GL_TRUE;
278 }
279 else if (format == GL_LUMINANCE && type == CHAN_TYPE
280 && ctx->_ImageTransferState==0) {
281 if (ctx->Visual.rgbMode) {
282 GLchan *src = (GLchan *) pixels
283 + (skipRows * rowLength + skipPixels);
284 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
285 /* no zooming */
286 GLint row;
287 ASSERT(drawWidth < MAX_WIDTH);
288 for (row=0; row<drawHeight; row++) {
289 GLint i;
290 for (i=0;i<drawWidth;i++) {
291 rgb[i][0] = src[i];
292 rgb[i][1] = src[i];
293 rgb[i][2] = src[i];
294 }
295 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
296 (CONST GLchan (*)[3]) rgb, NULL);
297 src += rowLength;
298 destY++;
299 }
300 }
301 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
302 /* upside-down */
303 GLint row;
304 ASSERT(drawWidth < MAX_WIDTH);
305 for (row=0; row<drawHeight; row++) {
306 GLint i;
307 for (i=0;i<drawWidth;i++) {
308 rgb[i][0] = src[i];
309 rgb[i][1] = src[i];
310 rgb[i][2] = src[i];
311 }
312 destY--;
313 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
314 (CONST GLchan (*)[3]) rgb, NULL);
315 src += rowLength;
316 }
317 }
318 else {
319 /* with zooming */
320 GLint row;
321 ASSERT(drawWidth < MAX_WIDTH);
322 for (row=0; row<drawHeight; row++) {
323 GLint i;
324 for (i=0;i<drawWidth;i++) {
325 rgb[i][0] = src[i];
326 rgb[i][1] = src[i];
327 rgb[i][2] = src[i];
328 }
329 _mesa_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
330 zSpan, 0, (CONST GLchan (*)[3]) rgb, zoomY0);
331 src += rowLength;
332 destY++;
333 }
334 }
335 }
336 return GL_TRUE;
337 }
338 else if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE
339 && ctx->_ImageTransferState == 0) {
340 if (ctx->Visual.rgbMode) {
341 GLchan *src = (GLchan *) pixels
342 + (skipRows * rowLength + skipPixels)*2;
343 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
344 /* no zooming */
345 GLint row;
346 ASSERT(drawWidth < MAX_WIDTH);
347 for (row=0; row<drawHeight; row++) {
348 GLint i;
349 GLchan *ptr = src;
350 for (i=0;i<drawWidth;i++) {
351 rgba[i][0] = *ptr;
352 rgba[i][1] = *ptr;
353 rgba[i][2] = *ptr++;
354 rgba[i][3] = *ptr++;
355 }
356 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
357 (CONST GLchan (*)[4]) rgba, NULL);
358 src += rowLength*2;
359 destY++;
360 }
361 }
362 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
363 /* upside-down */
364 GLint row;
365 ASSERT(drawWidth < MAX_WIDTH);
366 for (row=0; row<drawHeight; row++) {
367 GLint i;
368 GLchan *ptr = src;
369 for (i=0;i<drawWidth;i++) {
370 rgba[i][0] = *ptr;
371 rgba[i][1] = *ptr;
372 rgba[i][2] = *ptr++;
373 rgba[i][3] = *ptr++;
374 }
375 destY--;
376 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
377 (CONST GLchan (*)[4]) rgba, NULL);
378 src += rowLength*2;
379 }
380 }
381 else {
382 /* with zooming */
383 GLint row;
384 ASSERT(drawWidth < MAX_WIDTH);
385 for (row=0; row<drawHeight; row++) {
386 GLchan *ptr = src;
387 GLint i;
388 for (i=0;i<drawWidth;i++) {
389 rgba[i][0] = *ptr;
390 rgba[i][1] = *ptr;
391 rgba[i][2] = *ptr++;
392 rgba[i][3] = *ptr++;
393 }
394 _mesa_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
395 zSpan, 0, (CONST GLchan (*)[4]) rgba, zoomY0);
396 src += rowLength*2;
397 destY++;
398 }
399 }
400 }
401 return GL_TRUE;
402 }
403 else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
404 GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
405 if (ctx->Visual.rgbMode) {
406 /* convert CI data to RGBA */
407 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
408 /* no zooming */
409 GLint row;
410 for (row=0; row<drawHeight; row++) {
411 ASSERT(drawWidth < MAX_WIDTH);
412 _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
413 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
414 (const GLchan (*)[4]) rgba,
415 NULL);
416 src += rowLength;
417 destY++;
418 }
419 return GL_TRUE;
420 }
421 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
422 /* upside-down */
423 GLint row;
424 for (row=0; row<drawHeight; row++) {
425 ASSERT(drawWidth < MAX_WIDTH);
426 _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
427 destY--;
428 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
429 (CONST GLchan (*)[4]) rgba,
430 NULL);
431 src += rowLength;
432 }
433 return GL_TRUE;
434 }
435 else {
436 /* with zooming */
437 GLint row;
438 for (row=0; row<drawHeight; row++) {
439 ASSERT(drawWidth < MAX_WIDTH);
440 _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
441 _mesa_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
442 zSpan, 0, (CONST GLchan (*)[4]) rgba, zoomY0);
443 src += rowLength;
444 destY++;
445 }
446 return GL_TRUE;
447 }
448 }
449 else if (ctx->_ImageTransferState==0) {
450 /* write CI data to CI frame buffer */
451 GLint row;
452 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
453 /* no zooming */
454 for (row=0; row<drawHeight; row++) {
455 (*ctx->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY,
456 src, NULL);
457 src += rowLength;
458 destY++;
459 }
460 return GL_TRUE;
461 }
462 else {
463 /* with zooming */
464 return GL_FALSE;
465 }
466 }
467 }
468 else {
469 /* can't handle this pixel format and/or data type here */
470 return GL_FALSE;
471 }
472 }
473
474 /* can't do a simple draw, have to use slow path */
475 return GL_FALSE;
476 }
477
478
479
480 /*
481 * Do glDrawPixels of index pixels.
482 */
483 static void
484 draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
485 GLsizei width, GLsizei height,
486 GLenum type, const GLvoid *pixels )
487 {
488 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
489 const GLint desty = y;
490 GLint row, drawWidth;
491 GLdepth zspan[MAX_WIDTH];
492
493 drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
494
495 /* Fragment depth values */
496 if (ctx->Depth.Test || ctx->Fog.Enabled) {
497 GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * ctx->DepthMaxF);
498 GLint i;
499 for (i = 0; i < drawWidth; i++) {
500 zspan[i] = zval;
501 }
502 }
503
504 /*
505 * General solution
506 */
507 for (row = 0; row < height; row++, y++) {
508 GLuint indexes[MAX_WIDTH];
509 const GLvoid *source = _mesa_image_address(&ctx->Unpack,
510 pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
511 _mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT, indexes,
512 type, source, &ctx->Unpack,
513 ctx->_ImageTransferState);
514 if (zoom) {
515 _mesa_write_zoomed_index_span(ctx, drawWidth, x, y, zspan, 0, indexes, desty);
516 }
517 else {
518 _mesa_write_index_span(ctx, drawWidth, x, y, zspan, 0, indexes, GL_BITMAP);
519 }
520 }
521 }
522
523
524
525 /*
526 * Do glDrawPixels of stencil image. The image datatype may either
527 * be GLubyte or GLbitmap.
528 */
529 static void
530 draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
531 GLsizei width, GLsizei height,
532 GLenum type, const GLvoid *pixels )
533 {
534 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
535 const GLint desty = y;
536 GLint row, drawWidth;
537
538 if (type != GL_BYTE &&
539 type != GL_UNSIGNED_BYTE &&
540 type != GL_SHORT &&
541 type != GL_UNSIGNED_SHORT &&
542 type != GL_INT &&
543 type != GL_UNSIGNED_INT &&
544 type != GL_FLOAT &&
545 type != GL_BITMAP) {
546 _mesa_error( ctx, GL_INVALID_ENUM, "glDrawPixels(stencil type)");
547 return;
548 }
549
550 drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
551
552 for (row = 0; row < height; row++, y++) {
553 GLstencil values[MAX_WIDTH];
554 GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
555 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
556 const GLvoid *source = _mesa_image_address(&ctx->Unpack,
557 pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
558 _mesa_unpack_index_span(ctx, drawWidth, destType, values,
559 type, source, &ctx->Unpack,
560 ctx->_ImageTransferState);
561 if (ctx->_ImageTransferState & IMAGE_SHIFT_OFFSET_BIT) {
562 _mesa_shift_and_offset_stencil( ctx, drawWidth, values );
563 }
564 if (ctx->Pixel.MapStencilFlag) {
565 _mesa_map_stencil( ctx, drawWidth, values );
566 }
567
568 if (zoom) {
569 _mesa_write_zoomed_stencil_span( ctx, (GLuint) drawWidth, x, y,
570 values, desty );
571 }
572 else {
573 _mesa_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values );
574 }
575 }
576 }
577
578
579
580 /*
581 * Do a glDrawPixels of depth values.
582 */
583 static void
584 draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
585 GLsizei width, GLsizei height,
586 GLenum type, const GLvoid *pixels )
587 {
588 const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
589 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
590 const GLint desty = y;
591 GLchan rgba[MAX_WIDTH][4];
592 GLuint ispan[MAX_WIDTH];
593 GLint drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
594
595 if (type != GL_BYTE
596 && type != GL_UNSIGNED_BYTE
597 && type != GL_SHORT
598 && type != GL_UNSIGNED_SHORT
599 && type != GL_INT
600 && type != GL_UNSIGNED_INT
601 && type != GL_FLOAT) {
602 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawPixels(type)");
603 return;
604 }
605
606 /* Colors or indexes */
607 if (ctx->Visual.rgbMode) {
608 GLint i;
609 GLint r, g, b, a;
610 UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
611 UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
612 UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
613 UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
614 for (i = 0; i < drawWidth; i++) {
615 rgba[i][RCOMP] = r;
616 rgba[i][GCOMP] = g;
617 rgba[i][BCOMP] = b;
618 rgba[i][ACOMP] = a;
619 }
620 }
621 else {
622 GLint i;
623 for (i = 0; i < drawWidth; i++) {
624 ispan[i] = ctx->Current.RasterIndex;
625 }
626 }
627
628 if (type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
629 && !bias_or_scale && !zoom && ctx->Visual.rgbMode) {
630 /* Special case: directly write 16-bit depth values */
631 GLint row;
632 for (row = 0; row < height; row++, y++) {
633 GLdepth zspan[MAX_WIDTH];
634 const GLushort *zptr = (const GLushort *)
635 _mesa_image_address(&ctx->Unpack, pixels, width, height,
636 GL_DEPTH_COMPONENT, type, 0, row, 0);
637 GLint i;
638 for (i = 0; i < width; i++)
639 zspan[i] = zptr[i];
640 _mesa_write_rgba_span( ctx, width, x, y, zspan, 0, rgba, GL_BITMAP );
641 }
642 }
643 else if (type==GL_UNSIGNED_INT && ctx->Visual.depthBits == 32
644 && !bias_or_scale && !zoom && ctx->Visual.rgbMode) {
645 /* Special case: directly write 32-bit depth values */
646 GLint row;
647 for (row = 0; row < height; row++, y++) {
648 const GLuint *zptr = (const GLuint *)
649 _mesa_image_address(&ctx->Unpack, pixels, width, height,
650 GL_DEPTH_COMPONENT, type, 0, row, 0);
651 _mesa_write_rgba_span( ctx, width, x, y, zptr, 0, rgba, GL_BITMAP );
652 }
653 }
654 else {
655 /* General case */
656 GLint row;
657 for (row = 0; row < height; row++, y++) {
658 GLfloat fspan[MAX_WIDTH];
659 GLdepth zspan[MAX_WIDTH];
660 const GLvoid *src = _mesa_image_address(&ctx->Unpack,
661 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
662 _mesa_unpack_depth_span( ctx, drawWidth, fspan, type, src,
663 &ctx->Unpack );
664 /* clamp depth values to [0,1] and convert from floats to integers */
665 {
666 const GLfloat zs = ctx->DepthMaxF;
667 GLint i;
668 for (i = 0; i < drawWidth; i++) {
669 zspan[i] = (GLdepth) (fspan[i] * zs);
670 }
671 }
672
673 if (ctx->Visual.rgbMode) {
674 if (zoom) {
675 _mesa_write_zoomed_rgba_span(ctx, width, x, y, zspan, 0,
676 (const GLchan (*)[4]) rgba, desty);
677 }
678 else {
679 _mesa_write_rgba_span(ctx, width, x, y, zspan, 0, rgba, GL_BITMAP);
680 }
681 }
682 else {
683 if (zoom) {
684 _mesa_write_zoomed_index_span(ctx, width, x, y, zspan, 0,
685 ispan, GL_BITMAP);
686 }
687 else {
688 _mesa_write_index_span(ctx, width, x, y, zspan, 0,
689 ispan, GL_BITMAP);
690 }
691 }
692
693 }
694 }
695 }
696
697
698 /*
699 * Do glDrawPixels of RGBA pixels.
700 */
701 static void
702 draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
703 GLsizei width, GLsizei height,
704 GLenum format, GLenum type, const GLvoid *pixels )
705 {
706 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
707 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
708 const GLint desty = y;
709 GLdepth zspan[MAX_WIDTH];
710 GLboolean quickDraw;
711 GLfloat *convImage = NULL;
712 GLuint transferOps = ctx->_ImageTransferState;
713
714 if (!_mesa_is_legal_format_and_type(format, type)) {
715 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawPixels(format or type)");
716 return;
717 }
718
719 /* Try an optimized glDrawPixels first */
720 if (fast_draw_pixels(ctx, x, y, width, height, format, type, pixels))
721 return;
722
723 /* Fragment depth values */
724 if (ctx->Depth.Test || ctx->Fog.Enabled) {
725 /* fill in array of z values */
726 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->DepthMaxF);
727 GLint i;
728 for (i=0;i<width;i++) {
729 zspan[i] = z;
730 }
731 }
732
733
734 if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 && !zoom && x >= 0 && y >= 0
735 && x + width <= ctx->DrawBuffer->Width
736 && y + height <= ctx->DrawBuffer->Height) {
737 quickDraw = GL_TRUE;
738 }
739 else {
740 quickDraw = GL_FALSE;
741 }
742
743 if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
744 /* Convolution has to be handled specially. We'll create an
745 * intermediate image, applying all pixel transfer operations
746 * up to convolution. Then we'll convolve the image. Then
747 * we'll proceed with the rest of the transfer operations and
748 * rasterize the image.
749 */
750 GLint row;
751 GLfloat *dest, *tmpImage;
752
753 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
754 if (!tmpImage) {
755 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
756 return;
757 }
758 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
759 if (!convImage) {
760 FREE(tmpImage);
761 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
762 return;
763 }
764
765 /* Unpack the image and apply transfer ops up to convolution */
766 dest = tmpImage;
767 for (row = 0; row < height; row++) {
768 const GLvoid *source = _mesa_image_address(unpack,
769 pixels, width, height, format, type, 0, row, 0);
770 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, (GLfloat *) dest,
771 format, type, source, unpack,
772 transferOps & IMAGE_PRE_CONVOLUTION_BITS,
773 GL_FALSE);
774 dest += width * 4;
775 }
776
777 /* do convolution */
778 if (ctx->Pixel.Convolution2DEnabled) {
779 _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
780 }
781 else {
782 ASSERT(ctx->Pixel.Separable2DEnabled);
783 _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
784 }
785 FREE(tmpImage);
786
787 /* continue transfer ops and draw the convolved image */
788 unpack = &_mesa_native_packing;
789 pixels = convImage;
790 format = GL_RGBA;
791 type = GL_FLOAT;
792 transferOps &= IMAGE_POST_CONVOLUTION_BITS;
793 }
794
795 /*
796 * General solution
797 */
798 {
799 GLchan rgba[MAX_WIDTH][4];
800 GLint row;
801 if (width > MAX_WIDTH)
802 width = MAX_WIDTH;
803 for (row = 0; row < height; row++, y++) {
804 const GLvoid *source = _mesa_image_address(unpack,
805 pixels, width, height, format, type, 0, row, 0);
806 _mesa_unpack_chan_color_span(ctx, width, GL_RGBA, (GLchan *) rgba,
807 format, type, source, unpack,
808 transferOps);
809 if ((ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) ||
810 (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink))
811 continue;
812
813 if (ctx->Texture._ReallyEnabled && ctx->Pixel.PixelTextureEnabled) {
814 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], r[MAX_WIDTH], q[MAX_WIDTH];
815 GLchan primary_rgba[MAX_WIDTH][4];
816 GLuint unit;
817 /* XXX not sure how multitexture is supposed to work here */
818
819 MEMCPY(primary_rgba, rgba, 4 * width * sizeof(GLchan));
820
821 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
822 if (ctx->Texture.Unit[unit]._ReallyEnabled) {
823 _mesa_pixeltexgen(ctx, width, (const GLchan (*)[4]) rgba,
824 s, t, r, q);
825 _swrast_texture_fragments(ctx, unit, width, s, t, r, NULL,
826 (CONST GLchan (*)[4]) primary_rgba,
827 rgba);
828 }
829 }
830 }
831
832 if (quickDraw) {
833 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y,
834 (CONST GLchan (*)[]) rgba, NULL);
835 }
836 else if (zoom) {
837 _mesa_write_zoomed_rgba_span( ctx, width, x, y, zspan, 0,
838 (CONST GLchan (*)[]) rgba, desty );
839 }
840 else {
841 _mesa_write_rgba_span( ctx, (GLuint) width, x, y, zspan, 0,
842 rgba, GL_BITMAP);
843 }
844 }
845 }
846
847 if (convImage) {
848 FREE(convImage);
849 }
850 }
851
852
853
854 /*
855 * Execute glDrawPixels
856 */
857 void
858 _swrast_DrawPixels( GLcontext *ctx,
859 GLint x, GLint y,
860 GLsizei width, GLsizei height,
861 GLenum format, GLenum type,
862 const struct gl_pixelstore_attrib *unpack,
863 const GLvoid *pixels )
864 {
865 (void) unpack;
866
867 if (SWRAST_CONTEXT(ctx)->NewState)
868 _swrast_validate_derived( ctx );
869
870 switch (format) {
871 case GL_STENCIL_INDEX:
872 draw_stencil_pixels( ctx, x, y, width, height, type, pixels );
873 break;
874 case GL_DEPTH_COMPONENT:
875 draw_depth_pixels( ctx, x, y, width, height, type, pixels );
876 break;
877 case GL_COLOR_INDEX:
878 if (ctx->Visual.rgbMode)
879 draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels);
880 else
881 draw_index_pixels(ctx, x, y, width, height, type, pixels);
882 break;
883 case GL_RED:
884 case GL_GREEN:
885 case GL_BLUE:
886 case GL_ALPHA:
887 case GL_LUMINANCE:
888 case GL_LUMINANCE_ALPHA:
889 case GL_RGB:
890 case GL_BGR:
891 case GL_RGBA:
892 case GL_BGRA:
893 case GL_ABGR_EXT:
894 draw_rgba_pixels(ctx, x, y, width, height, format, type, pixels);
895 break;
896 default:
897 _mesa_error( ctx, GL_INVALID_ENUM, "glDrawPixels(format)" );
898 }
899 }
900