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