3bd164159d97ad73b184888c4aa7f57a28676e17
[mesa.git] / src / mesa / main / drawpix.c
1 /* $Id: drawpix.c,v 1.10 1999/11/26 16:27:05 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
7 * Copyright (C) 1999 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 #ifdef PC_HEADER
29 #include "all.h"
30 #else
31 #include "glheader.h"
32 #include "context.h"
33 #include "drawpix.h"
34 #include "feedback.h"
35 #include "image.h"
36 #include "macros.h"
37 #include "mmath.h"
38 #include "pixel.h"
39 #include "span.h"
40 #include "stencil.h"
41 #include "types.h"
42 #include "zoom.h"
43 #endif
44
45
46
47 /*
48 * Given the dest position, size and skipPixels and skipRows values
49 * for a glDrawPixels command, perform clipping of the image bounds
50 * so the result lies withing the context's buffer bounds.
51 * Return: GL_TRUE if image is ready for drawing
52 * GL_FALSE if image was completely clipped away (draw nothing)
53 */
54 GLboolean
55 _mesa_clip_pixelrect(const GLcontext *ctx,
56 GLint *destX, GLint *destY,
57 GLsizei *width, GLsizei *height,
58 GLint *skipPixels, GLint *skipRows)
59 {
60 const GLframebuffer *buffer = ctx->DrawBuffer;
61
62 /* left clipping */
63 if (*destX < buffer->Xmin) {
64 *skipPixels += (buffer->Xmin - *destX);
65 *width -= (buffer->Xmin - *destX);
66 *destX = buffer->Xmin;
67 }
68 /* right clipping */
69 if (*destX + *width > buffer->Xmax)
70 *width -= (*destX + *width - buffer->Xmax - 1);
71
72 if (*width <= 0)
73 return GL_FALSE;
74
75 /* bottom clipping */
76 if (*destY < buffer->Ymin) {
77 *skipRows += (buffer->Ymin - *destY);
78 *height -= (buffer->Ymin - *destY);
79 *destY = buffer->Ymin;
80 }
81 /* top clipping */
82 if (*destY + *height > buffer->Ymax)
83 *height -= (*destY + *height - buffer->Ymax - 1);
84
85 if (*height <= 0)
86 return GL_TRUE;
87
88 return GL_TRUE;
89 }
90
91
92
93 /*
94 * Try to do a fast and simple RGB(a) glDrawPixels.
95 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
96 */
97 static GLboolean
98 simple_DrawPixels( GLcontext *ctx, GLint x, GLint y,
99 GLsizei width, GLsizei height, GLenum format, GLenum type,
100 const GLvoid *pixels )
101 {
102 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
103 GLubyte rgb[MAX_WIDTH][3];
104 GLubyte rgba[MAX_WIDTH][4];
105
106 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glDrawPixels",
107 GL_FALSE);
108
109
110 if (!ctx->Current.RasterPosValid) {
111 /* no-op */
112 return GL_TRUE;
113 }
114
115 if (ctx->NewState) {
116 gl_update_state(ctx);
117 }
118
119 /* see if device driver can do the drawpix */
120 if (ctx->Driver.DrawPixels
121 && (*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type,
122 unpack, pixels)) {
123 return GL_TRUE;
124 }
125
126 if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0
127 && ctx->Pixel.RedBias==0.0 && ctx->Pixel.RedScale==1.0
128 && ctx->Pixel.GreenBias==0.0 && ctx->Pixel.GreenScale==1.0
129 && ctx->Pixel.BlueBias==0.0 && ctx->Pixel.BlueScale==1.0
130 && ctx->Pixel.AlphaBias==0.0 && ctx->Pixel.AlphaScale==1.0
131 && ctx->Pixel.IndexShift==0 && ctx->Pixel.IndexOffset==0
132 && ctx->Pixel.MapColorFlag==0
133 && unpack->Alignment==1
134 && !unpack->SwapBytes
135 && !unpack->LsbFirst) {
136
137 GLint destX = x;
138 GLint destY = y;
139 GLint drawWidth = width; /* actual width drawn */
140 GLint drawHeight = height; /* actual height drawn */
141 GLint skipPixels = unpack->SkipPixels;
142 GLint skipRows = unpack->SkipRows;
143 GLint rowLength;
144 GLdepth zSpan[MAX_WIDTH]; /* only used when zooming */
145 GLint zoomY0;
146
147 if (unpack->RowLength > 0)
148 rowLength = unpack->RowLength;
149 else
150 rowLength = width;
151
152 /* If we're not using pixel zoom then do all clipping calculations
153 * now. Otherwise, we'll let the gl_write_zoomed_*_span() functions
154 * handle the clipping.
155 */
156 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
157 /* horizontal clipping */
158 if (destX < ctx->DrawBuffer->Xmin) {
159 skipPixels += (ctx->DrawBuffer->Xmin - destX);
160 drawWidth -= (ctx->DrawBuffer->Xmin - destX);
161 destX = ctx->DrawBuffer->Xmin;
162 }
163 if (destX + drawWidth > ctx->DrawBuffer->Xmax)
164 drawWidth -= (destX + drawWidth - ctx->DrawBuffer->Xmax - 1);
165 if (drawWidth <= 0)
166 return GL_TRUE;
167
168 /* vertical clipping */
169 if (destY < ctx->DrawBuffer->Ymin) {
170 skipRows += (ctx->DrawBuffer->Ymin - destY);
171 drawHeight -= (ctx->DrawBuffer->Ymin - destY);
172 destY = ctx->DrawBuffer->Ymin;
173 }
174 if (destY + drawHeight > ctx->DrawBuffer->Ymax)
175 drawHeight -= (destY + drawHeight - ctx->DrawBuffer->Ymax - 1);
176 if (drawHeight <= 0)
177 return GL_TRUE;
178
179 zoomY0 = 0; /* not used - silence compiler warning */
180 }
181 else {
182 /* setup array of fragment Z value to pass to zoom function */
183 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
184 GLint i;
185 assert(drawWidth < MAX_WIDTH);
186 for (i=0; i<drawWidth; i++)
187 zSpan[i] = z;
188
189 /* save Y value of first row */
190 zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
191 }
192
193
194 /*
195 * Ready to draw!
196 * The window region at (destX, destY) of size (drawWidth, drawHeight)
197 * will be written to.
198 * We'll take pixel data from buffer pointed to by "pixels" but we'll
199 * skip "skipRows" rows and skip "skipPixels" pixels/row.
200 */
201
202 if (format==GL_RGBA && type==GL_UNSIGNED_BYTE) {
203 if (ctx->Visual->RGBAflag) {
204 GLubyte *src = (GLubyte *) pixels
205 + (skipRows * rowLength + skipPixels) * 4;
206 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
207 /* no zooming */
208 GLint row;
209 for (row=0; row<drawHeight; row++) {
210 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
211 (void *) src, NULL);
212 src += rowLength * 4;
213 destY++;
214 }
215 }
216 else {
217 /* with zooming */
218 GLint row;
219 for (row=0; row<drawHeight; row++) {
220 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
221 zSpan, (void *) src, zoomY0);
222 src += rowLength * 4;
223 destY++;
224 }
225 }
226 }
227 return GL_TRUE;
228 }
229 else if (format==GL_RGB && type==GL_UNSIGNED_BYTE) {
230 if (ctx->Visual->RGBAflag) {
231 GLubyte *src = (GLubyte *) pixels
232 + (skipRows * rowLength + skipPixels) * 3;
233 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
234 GLint row;
235 for (row=0; row<drawHeight; row++) {
236 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
237 (void *) src, NULL);
238 src += rowLength * 3;
239 destY++;
240 }
241 }
242 else {
243 /* with zooming */
244 GLint row;
245 for (row=0; row<drawHeight; row++) {
246 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
247 zSpan, (void *) src, zoomY0);
248 src += rowLength * 3;
249 destY++;
250 }
251 }
252 }
253 return GL_TRUE;
254 }
255 else if (format==GL_LUMINANCE && type==GL_UNSIGNED_BYTE) {
256 if (ctx->Visual->RGBAflag) {
257 GLubyte *src = (GLubyte *) pixels
258 + (skipRows * rowLength + skipPixels);
259 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
260 /* no zooming */
261 GLint row;
262 assert(drawWidth < MAX_WIDTH);
263 for (row=0; row<drawHeight; row++) {
264 GLint i;
265 for (i=0;i<drawWidth;i++) {
266 rgb[i][0] = src[i];
267 rgb[i][1] = src[i];
268 rgb[i][2] = src[i];
269 }
270 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
271 (void *) rgb, NULL);
272 src += rowLength;
273 destY++;
274 }
275 }
276 else {
277 /* with zooming */
278 GLint row;
279 assert(drawWidth < MAX_WIDTH);
280 for (row=0; row<drawHeight; row++) {
281 GLint i;
282 for (i=0;i<drawWidth;i++) {
283 rgb[i][0] = src[i];
284 rgb[i][1] = src[i];
285 rgb[i][2] = src[i];
286 }
287 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
288 zSpan, (void *) rgb, zoomY0);
289 src += rowLength;
290 destY++;
291 }
292 }
293 }
294 return GL_TRUE;
295 }
296 else if (format==GL_LUMINANCE_ALPHA && type==GL_UNSIGNED_BYTE) {
297 if (ctx->Visual->RGBAflag) {
298 GLubyte *src = (GLubyte *) pixels
299 + (skipRows * rowLength + skipPixels)*2;
300 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
301 /* no zooming */
302 GLint row;
303 assert(drawWidth < MAX_WIDTH);
304 for (row=0; row<drawHeight; row++) {
305 GLint i;
306 GLubyte *ptr = src;
307 for (i=0;i<drawWidth;i++) {
308 rgba[i][0] = *ptr;
309 rgba[i][1] = *ptr;
310 rgba[i][2] = *ptr++;
311 rgba[i][3] = *ptr++;
312 }
313 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
314 (void *) rgba, NULL);
315 src += rowLength*2;
316 destY++;
317 }
318 }
319 else {
320 /* with zooming */
321 GLint row;
322 assert(drawWidth < MAX_WIDTH);
323 for (row=0; row<drawHeight; row++) {
324 GLubyte *ptr = src;
325 GLint i;
326 for (i=0;i<drawWidth;i++) {
327 rgba[i][0] = *ptr;
328 rgba[i][1] = *ptr;
329 rgba[i][2] = *ptr++;
330 rgba[i][3] = *ptr++;
331 }
332 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
333 zSpan, (void *) rgba, zoomY0);
334 src += rowLength*2;
335 destY++;
336 }
337 }
338 }
339 return GL_TRUE;
340 }
341 else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
342 GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
343 if (ctx->Visual->RGBAflag) {
344 /* convert CI data to RGBA */
345 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
346 /* no zooming */
347 GLint row;
348 for (row=0; row<drawHeight; row++) {
349 assert(drawWidth < MAX_WIDTH);
350 gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
351 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
352 (const GLubyte (*)[4])rgba,
353 NULL);
354 src += rowLength;
355 destY++;
356 }
357 return GL_TRUE;
358 }
359 else {
360 /* with zooming */
361 GLint row;
362 for (row=0; row<drawHeight; row++) {
363 assert(drawWidth < MAX_WIDTH);
364 gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
365 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
366 zSpan, (void *) rgba, zoomY0);
367 src += rowLength;
368 destY++;
369 }
370 return GL_TRUE;
371 }
372 }
373 else {
374 /* write CI data to CI frame buffer */
375 GLint row;
376 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
377 /* no zooming */
378 for (row=0; row<drawHeight; row++) {
379 (*ctx->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY,
380 src, NULL);
381 src += rowLength;
382 destY++;
383 }
384 return GL_TRUE;
385 }
386 else {
387 /* with zooming */
388 return GL_FALSE;
389 }
390 }
391 }
392 else {
393 /* can't handle this pixel format and/or data type here */
394 return GL_FALSE;
395 }
396 }
397
398 /* can't do a simple draw, have to use slow path */
399 return GL_FALSE;
400 }
401
402
403
404 /*
405 * Do glDrawPixels of index pixels.
406 */
407 static void
408 draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
409 GLsizei width, GLsizei height,
410 GLenum type, const GLvoid *pixels )
411 {
412 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
413 const GLint desty = y;
414 GLint row, drawWidth;
415 GLdepth zspan[MAX_WIDTH];
416
417 drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
418
419 /* Fragment depth values */
420 if (ctx->Depth.Test || ctx->Fog.Enabled) {
421 GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
422 GLint i;
423 for (i = 0; i < drawWidth; i++) {
424 zspan[i] = zval;
425 }
426 }
427
428 /*
429 * General solution
430 */
431 for (row = 0; row < height; row++, y++) {
432 GLuint indexes[MAX_WIDTH];
433 const GLvoid *source = gl_pixel_addr_in_image(&ctx->Unpack,
434 pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
435 _mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT, indexes,
436 type, source, &ctx->Unpack, GL_TRUE);
437 if (zoom) {
438 gl_write_zoomed_index_span(ctx, drawWidth, x, y, zspan, indexes, desty);
439 }
440 else {
441 gl_write_index_span(ctx, drawWidth, x, y, zspan, indexes, GL_BITMAP);
442 }
443 }
444 }
445
446
447
448 /*
449 * Do glDrawPixels of stencil image. The image datatype may either
450 * be GLubyte or GLbitmap.
451 */
452 static void
453 draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
454 GLsizei width, GLsizei height,
455 GLenum type, const GLvoid *pixels )
456 {
457 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
458 const GLint desty = y;
459 GLint row, drawWidth;
460
461 if (type != GL_BYTE &&
462 type != GL_UNSIGNED_BYTE &&
463 type != GL_SHORT &&
464 type != GL_UNSIGNED_SHORT &&
465 type != GL_INT &&
466 type != GL_UNSIGNED_INT &&
467 type != GL_FLOAT &&
468 type != GL_BITMAP) {
469 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(stencil type)");
470 return;
471 }
472
473 drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
474
475 for (row = 0; row < height; row++, y++) {
476 GLstencil values[MAX_WIDTH];
477 GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
478 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
479 const GLvoid *source = gl_pixel_addr_in_image(&ctx->Unpack,
480 pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
481 _mesa_unpack_index_span(ctx, drawWidth, destType, values,
482 type, source, &ctx->Unpack, GL_TRUE);
483
484 if (zoom) {
485 gl_write_zoomed_stencil_span( ctx, (GLuint) drawWidth, x, y,
486 values, desty );
487 }
488 else {
489 gl_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values );
490 }
491 }
492 }
493
494
495
496 /*
497 * Do a glDrawPixels of depth values.
498 */
499 static void
500 draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
501 GLsizei width, GLsizei height,
502 GLenum type, const GLvoid *pixels )
503 {
504 const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
505 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
506 const GLint desty = y;
507 GLubyte rgba[MAX_WIDTH][4];
508 GLuint ispan[MAX_WIDTH];
509 GLint drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
510
511 if (type != GL_UNSIGNED_BYTE
512 && type != GL_UNSIGNED_BYTE
513 && type != GL_UNSIGNED_SHORT
514 && type != GL_UNSIGNED_SHORT
515 && type != GL_UNSIGNED_INT
516 && type != GL_UNSIGNED_INT
517 && type != GL_FLOAT) {
518 gl_error(ctx, GL_INVALID_ENUM, "glDrawPixels(type)");
519 return;
520 }
521
522 /* Colors or indexes */
523 if (ctx->Visual->RGBAflag) {
524 GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F);
525 GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F);
526 GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F);
527 GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F);
528 GLint i;
529 for (i = 0; i < drawWidth; i++) {
530 rgba[i][RCOMP] = r;
531 rgba[i][GCOMP] = g;
532 rgba[i][BCOMP] = b;
533 rgba[i][ACOMP] = a;
534 }
535 }
536 else {
537 GLint i;
538 for (i = 0; i < drawWidth; i++) {
539 ispan[i] = ctx->Current.RasterIndex;
540 }
541 }
542
543 if (type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
544 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
545 /* Special case: directly write 16-bit depth values */
546 GLint row;
547 for (row = 0; row < height; row++, y++) {
548 const GLdepth *zptr = gl_pixel_addr_in_image(&ctx->Unpack,
549 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
550 gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
551 }
552 }
553 else if (type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint)
554 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
555 /* Special case: directly write 32-bit depth values */
556 GLint i, row;
557 /* Compute shift value to scale 32-bit uints down to depth values. */
558 GLuint shift = 0;
559 GLuint max = MAX_DEPTH;
560 while ((max & 0x80000000) == 0) {
561 max = max << 1;
562 shift++;
563 }
564 for (row = 0; row < height; row++, y++) {
565 GLdepth zspan[MAX_WIDTH];
566 const GLdepth *zptr = gl_pixel_addr_in_image(&ctx->Unpack,
567 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
568 for (i=0;i<width;i++) {
569 zspan[i] = zptr[i] >> shift;
570 }
571 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
572 }
573 }
574 else {
575 /* General case */
576 GLint row;
577 for (row = 0; row < height; row++, y++) {
578 GLdepth zspan[MAX_WIDTH];
579 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack,
580 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
581 _mesa_unpack_depth_span( ctx, drawWidth, zspan, type, src,
582 &ctx->Unpack, GL_TRUE );
583 if (ctx->Visual->RGBAflag) {
584 if (zoom) {
585 gl_write_zoomed_rgba_span(ctx, width, x, y, zspan,
586 (const GLubyte (*)[4])rgba, desty);
587 }
588 else {
589 gl_write_rgba_span(ctx, width, x, y, zspan, rgba, GL_BITMAP);
590 }
591 }
592 else {
593 if (zoom) {
594 gl_write_zoomed_index_span(ctx, width, x, y, zspan,
595 ispan, GL_BITMAP);
596 }
597 else {
598 gl_write_index_span(ctx, width, x, y, zspan, ispan, GL_BITMAP);
599 }
600 }
601
602 }
603 }
604 }
605
606
607 /*
608 * Do glDrawPixels of RGBA pixels.
609 */
610 static void
611 draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
612 GLsizei width, GLsizei height,
613 GLenum format, GLenum type, const GLvoid *pixels )
614 {
615 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
616 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
617 const GLint desty = y;
618 GLdepth zspan[MAX_WIDTH];
619 GLboolean quickDraw;
620
621 /* Try an optimized glDrawPixels first */
622 if (simple_DrawPixels(ctx, x, y, width, height, format, type, pixels))
623 return;
624
625 /* Fragment depth values */
626 if (ctx->Depth.Test || ctx->Fog.Enabled) {
627 /* fill in array of z values */
628 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
629 GLint i;
630 for (i=0;i<width;i++) {
631 zspan[i] = z;
632 }
633 }
634
635
636 if (ctx->RasterMask == 0 && !zoom
637 && x >= 0 && y >= 0
638 && x + width <= ctx->DrawBuffer->Width
639 && y + height <= ctx->DrawBuffer->Height) {
640 quickDraw = GL_TRUE;
641 }
642 else {
643 quickDraw = GL_FALSE;
644 }
645
646 /*
647 * General solution
648 */
649 {
650 GLubyte rgba[MAX_WIDTH][4];
651 GLint row;
652 if (width > MAX_WIDTH)
653 width = MAX_WIDTH;
654 for (row = 0; row < height; row++, y++) {
655 const GLvoid *source = gl_pixel_addr_in_image(unpack,
656 pixels, width, height, format, type, 0, row, 0);
657 _mesa_unpack_ubyte_color_span(ctx, width, GL_RGBA, (void*) rgba,
658 format, type, source, unpack, GL_TRUE);
659
660 if (quickDraw) {
661 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y,
662 (CONST GLubyte (*)[]) rgba, NULL);
663 }
664 else if (zoom) {
665 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
666 (CONST GLubyte (*)[]) rgba, desty );
667 }
668 else {
669 gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP);
670 }
671 }
672 }
673 }
674
675
676
677 /*
678 * Execute glDrawPixels
679 */
680 void
681 _mesa_DrawPixels( GLsizei width, GLsizei height,
682 GLenum format, GLenum type, const GLvoid *pixels )
683 {
684 GET_CURRENT_CONTEXT(ctx);
685 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels");
686
687 if (ctx->RenderMode==GL_RENDER) {
688 GLint x, y;
689 if (!pixels || !ctx->Current.RasterPosValid) {
690 return;
691 }
692
693 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
694 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
695
696 switch (format) {
697 case GL_STENCIL_INDEX:
698 draw_stencil_pixels( ctx, x, y, width, height, type, pixels );
699 break;
700 case GL_DEPTH_COMPONENT:
701 draw_depth_pixels( ctx, x, y, width, height, type, pixels );
702 break;
703 case GL_COLOR_INDEX:
704 if (ctx->Visual->RGBAflag)
705 draw_index_pixels(ctx, x, y, width, height, type, pixels);
706 else
707 draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels);
708 break;
709 case GL_RED:
710 case GL_GREEN:
711 case GL_BLUE:
712 case GL_ALPHA:
713 case GL_LUMINANCE:
714 case GL_LUMINANCE_ALPHA:
715 case GL_RGB:
716 case GL_BGR:
717 case GL_RGBA:
718 case GL_BGRA:
719 case GL_ABGR_EXT:
720 draw_rgba_pixels(ctx, x, y, width, height, format, type, pixels);
721 break;
722 default:
723 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(format)" );
724 return;
725 }
726 }
727 else if (ctx->RenderMode==GL_FEEDBACK) {
728 if (ctx->Current.RasterPosValid) {
729 GLfloat color[4];
730 GLfloat texcoord[4], invq;
731 UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor);
732 invq = 1.0F / ctx->Current.Texcoord[0][3];
733 texcoord[0] = ctx->Current.Texcoord[0][0] * invq;
734 texcoord[1] = ctx->Current.Texcoord[0][1] * invq;
735 texcoord[2] = ctx->Current.Texcoord[0][2] * invq;
736 texcoord[3] = ctx->Current.Texcoord[0][3];
737 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
738 gl_feedback_vertex( ctx,
739 ctx->Current.RasterPos,
740 color, ctx->Current.Index, texcoord );
741 }
742 }
743 else if (ctx->RenderMode==GL_SELECT) {
744 if (ctx->Current.RasterPosValid) {
745 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
746 }
747 }
748 }
749