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