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