1 /* $Id: drawpix.c,v 1.16 1998/02/03 23:45:02 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 2.4
6 * Copyright (C) 1995-1997 Brian Paul
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23
24 /*
25 * $Log: drawpix.c,v $
26 * Revision 1.16 1998/02/03 23:45:02 brianp
27 * added casts to prevent warnings with Amiga StormC compiler
28 *
29 * Revision 1.15 1997/08/26 02:10:11 brianp
30 * another bug fix related to glPixelStore()
31 *
32 * Revision 1.14 1997/08/24 02:31:23 brianp
33 * bug fix: glPixelStore() params weren't ignored during display list execute
34 *
35 * Revision 1.13 1997/07/24 01:25:01 brianp
36 * changed precompiled header symbol from PCH to PC_HEADER
37 *
38 * Revision 1.12 1997/06/20 02:18:23 brianp
39 * replaced Current.IntColor with Current.ByteColor
40 *
41 * Revision 1.11 1997/05/28 03:24:22 brianp
42 * added precompiled header (PCH) support
43 *
44 * Revision 1.10 1997/04/24 00:18:56 brianp
45 * added some missing UNDEFARRAY()s. Reported by Randy Frank.
46 *
47 * Revision 1.9 1997/04/20 20:28:49 brianp
48 * replaced abort() with gl_problem()
49 *
50 * Revision 1.8 1997/04/11 23:24:25 brianp
51 * move call to gl_update_state() into gl_DrawPixels() from drawpixels()
52 *
53 * Revision 1.7 1997/03/18 01:55:47 brianp
54 * only generate feedback/selection if raster position is valid
55 *
56 * Revision 1.6 1997/02/10 20:26:57 brianp
57 * fixed memory leak in quickdraw_rgb()
58 *
59 * Revision 1.5 1997/02/03 20:30:31 brianp
60 * added a few DEFARRAY macros for BeOS
61 *
62 * Revision 1.4 1996/10/16 00:58:53 brianp
63 * renamed gl_drawpixels() to drawpixels()
64 *
65 * Revision 1.3 1996/09/27 01:26:25 brianp
66 * added missing default cases to switches
67 *
68 * Revision 1.2 1996/09/15 14:17:30 brianp
69 * now use GLframebuffer and GLvisual
70 *
71 * Revision 1.1 1996/09/13 01:38:16 brianp
72 * Initial revision
73 *
74 */
75
76
77 #ifdef PC_HEADER
78 #include "all.h"
79 #else
80 #include <stdlib.h>
81 #include <string.h>
82 #include "context.h"
83 #include "drawpix.h"
84 #include "feedback.h"
85 #include "dlist.h"
86 #include "macros.h"
87 #include "pixel.h"
88 #include "span.h"
89 #include "stencil.h"
90 #include "types.h"
91 #endif
92
93
94
95 /* TODO: apply texture mapping to fragments */
96
97
98
draw_index_pixels(GLcontext * ctx,GLsizei width,GLsizei height,GLenum type,const GLvoid * pixels)99 static void draw_index_pixels( GLcontext* ctx, GLsizei width, GLsizei height,
100 GLenum type, const GLvoid *pixels )
101 {
102 GLint x, y, desty;
103 GLuint i, j;
104 GLdepth zspan[MAX_WIDTH];
105 GLboolean zoom;
106
107 zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
108
109 /* Position, depth of pixels */
110 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
111 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
112 desty = y;
113 if (ctx->Depth.Test) {
114 GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
115 for (i=0;i<width;i++) {
116 zspan[i] = zval;
117 }
118 }
119
120 /* process the image row by row */
121 for (i=0;i<height;i++,y++) {
122 GLuint ispan[MAX_WIDTH];
123
124 /* convert to uints */
125 switch (type) {
126 case GL_UNSIGNED_BYTE:
127 {
128 GLubyte *src = (GLubyte *) pixels + i * width;
129 for (j=0;j<width;j++) {
130 ispan[j] = (GLuint) *src++;
131 }
132 }
133 break;
134 case GL_BYTE:
135 {
136 GLbyte *src = (GLbyte *) pixels + i * width;
137 for (j=0;j<width;j++) {
138 ispan[j] = (GLuint) *src++;
139 }
140 }
141 break;
142 case GL_UNSIGNED_SHORT:
143 {
144 GLushort *src = (GLushort *) pixels + i * width;
145 for (j=0;j<width;j++) {
146 ispan[j] = (GLuint) *src++;
147 }
148 }
149 break;
150 case GL_SHORT:
151 {
152 GLshort *src = (GLshort *) pixels + i * width;
153 for (j=0;j<width;j++) {
154 ispan[j] = (GLuint) *src++;
155 }
156 }
157 break;
158 case GL_UNSIGNED_INT:
159 {
160 GLuint *src = (GLuint *) pixels + i * width;
161 for (j=0;j<width;j++) {
162 ispan[j] = *src++;
163 }
164 }
165 break;
166 case GL_INT:
167 {
168 GLint *src = (GLint *) pixels + i * width;
169 for (j=0;j<width;j++) {
170 ispan[j] = (GLuint) *src++;
171 }
172 }
173 break;
174 case GL_BITMAP:
175 /* TODO */
176 break;
177 case GL_FLOAT:
178 {
179 GLfloat *src = (GLfloat *) pixels + i * width;
180 for (j=0;j<width;j++) {
181 ispan[j] = (GLuint) (GLint) *src++;
182 }
183 }
184 break;
185 default:
186 gl_error( ctx, GL_INVALID_ENUM, "Internal: draw_index_pixels" );
187 }
188
189 /* apply shift and offset */
190 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
191 if (ctx->Pixel.IndexShift>=0) {
192 for (j=0;j<width;j++) {
193 ispan[j] = (ispan[j] << ctx->Pixel.IndexShift)
194 + ctx->Pixel.IndexOffset;
195 }
196 }
197 else {
198 for (j=0;j<width;j++) {
199 ispan[j] = (ispan[j] >> -ctx->Pixel.IndexShift)
200 + ctx->Pixel.IndexOffset;
201 }
202 }
203 }
204
205 if (ctx->Visual->RGBAflag) {
206 /* Convert index to RGBA and write to frame buffer */
207 GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
208 GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
209 for (j=0;j<width;j++) {
210 red[j] = (GLint) (ctx->Pixel.MapItoR[ispan[j]] * ctx->Visual->RedScale);
211 green[j] = (GLint) (ctx->Pixel.MapItoG[ispan[j]] * ctx->Visual->GreenScale);
212 blue[j] = (GLint) (ctx->Pixel.MapItoB[ispan[j]] * ctx->Visual->BlueScale);
213 alpha[j] = (GLint) (ctx->Pixel.MapItoA[ispan[j]] * ctx->Visual->AlphaScale);
214 }
215 if (zoom) {
216 gl_write_zoomed_color_span( ctx, width, x, y, zspan,
217 red, green, blue, alpha, desty );
218 }
219 else {
220 gl_write_color_span( ctx, width, x, y, zspan,
221 red, green, blue, alpha, GL_BITMAP );
222 }
223 }
224 else {
225 /* optionally apply index map then write to frame buffer */
226 if (ctx->Pixel.MapColorFlag) {
227 for (j=0;j<width;j++) {
228 ispan[j] = ctx->Pixel.MapItoI[ispan[j]];
229 }
230 }
231 if (zoom) {
232 gl_write_zoomed_index_span( ctx, width, x, y, zspan, ispan, desty );
233 }
234 else {
235 gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
236 }
237 }
238 }
239
240 }
241
242
243
draw_stencil_pixels(GLcontext * ctx,GLsizei width,GLsizei height,GLenum type,const GLvoid * pixels)244 static void draw_stencil_pixels( GLcontext* ctx, GLsizei width, GLsizei height,
245 GLenum type, const GLvoid *pixels )
246 {
247 GLint x, y, desty;
248 GLuint i, j;
249 GLboolean zoom;
250
251 zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
252
253 /* Position, depth of pixels */
254 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
255 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
256 desty = y;
257
258 /* process the image row by row */
259 for (i=0;i<height;i++,y++) {
260 GLubyte stencil[MAX_WIDTH];
261
262 /* convert to ubytes */
263 switch (type) {
264 case GL_UNSIGNED_BYTE:
265 {
266 GLubyte *src = (GLubyte *) pixels + i * width;
267 MEMCPY( stencil, src, width );
268 }
269 break;
270 case GL_BYTE:
271 {
272 GLbyte *src = (GLbyte *) pixels + i * width;
273 MEMCPY( stencil, src, width );
274 }
275 break;
276 case GL_UNSIGNED_SHORT:
277 {
278 GLushort *src = (GLushort *) pixels + i * width;
279 for (j=0;j<width;j++) {
280 stencil[j] = (GLubyte) ((*src++) & 0xff);
281 }
282 }
283 break;
284 case GL_SHORT:
285 {
286 GLshort *src = (GLshort *) pixels + i * width;
287 for (j=0;j<width;j++) {
288 stencil[j] = (GLubyte) ((*src++) & 0xff);
289 }
290 }
291 break;
292 case GL_UNSIGNED_INT:
293 {
294 GLuint *src = (GLuint *) pixels + i * width;
295 for (j=0;j<width;j++) {
296 stencil[j] = (GLubyte) ((*src++) & 0xff);
297 }
298 }
299 break;
300 case GL_INT:
301 {
302 GLint *src = (GLint *) pixels + i * width;
303 for (j=0;j<width;j++) {
304 stencil[j] = (GLubyte) ((*src++) & 0xff);
305 }
306 }
307 break;
308 case GL_BITMAP:
309 /* TODO */
310 break;
311 case GL_FLOAT:
312 {
313 GLfloat *src = (GLfloat *) pixels + i * width;
314 for (j=0;j<width;j++) {
315 stencil[j] = (GLubyte) (((GLint) *src++) & 0xff);
316 }
317 }
318 break;
319 default:
320 gl_error( ctx, GL_INVALID_ENUM, "Internal: draw_stencil_pixels" );
321 }
322
323 /* apply shift and offset */
324 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
325 if (ctx->Pixel.IndexShift>=0) {
326 for (j=0;j<width;j++) {
327 stencil[j] = (stencil[j] << ctx->Pixel.IndexShift)
328 + ctx->Pixel.IndexOffset;
329 }
330 }
331 else {
332 for (j=0;j<width;j++) {
333 stencil[j] = (stencil[j] >> -ctx->Pixel.IndexShift)
334 + ctx->Pixel.IndexOffset;
335 }
336 }
337 }
338
339 /* mapping */
340 if (ctx->Pixel.MapStencilFlag) {
341 for (j=0;j<width;j++) {
342 stencil[j] = ctx->Pixel.MapStoS[ stencil[j] ];
343 }
344 }
345
346 /* write stencil values to stencil buffer */
347 if (zoom) {
348 gl_write_zoomed_stencil_span( ctx, (GLuint) width, x, y, stencil, desty );
349 }
350 else {
351 gl_write_stencil_span( ctx, (GLuint) width, x, y, stencil );
352 }
353 }
354 }
355
356
357
draw_depth_pixels(GLcontext * ctx,GLsizei width,GLsizei height,GLenum type,const GLvoid * pixels)358 static void draw_depth_pixels( GLcontext* ctx, GLsizei width, GLsizei height,
359 GLenum type, const GLvoid *pixels )
360 {
361 GLint x, y, desty;
362 GLubyte red[MAX_WIDTH], green[MAX_WIDTH], blue[MAX_WIDTH], alpha[MAX_WIDTH];
363 GLuint ispan[MAX_WIDTH];
364 GLboolean bias_or_scale;
365 GLboolean zoom;
366
367 bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
368 zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
369
370 /* Position, depth of pixels */
371 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
372 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
373 desty = y;
374
375 /* Color or index */
376 if (ctx->Visual->RGBAflag) {
377 GLint r, g, b, a;
378 r = (GLint) (ctx->Current.RasterColor[0] * ctx->Visual->RedScale);
379 g = (GLint) (ctx->Current.RasterColor[1] * ctx->Visual->GreenScale);
380 b = (GLint) (ctx->Current.RasterColor[2] * ctx->Visual->BlueScale);
381 a = (GLint) (ctx->Current.RasterColor[3] * ctx->Visual->AlphaScale);
382 MEMSET( red, r, width );
383 MEMSET( green, g, width );
384 MEMSET( blue, b, width );
385 MEMSET( alpha, a, width );
386 }
387 else {
388 GLuint i;
389 for (i=0;i<width;i++) {
390 ispan[i] = ctx->Current.RasterIndex;
391 }
392 }
393
394 if (type==GL_UNSIGNED_INT && !bias_or_scale && !zoom && ctx->Visual->RGBAflag)
395 {
396 /* Special case: directly write 32-bit depth values */
397 GLuint i, j;
398 /* Compute shift value to scale 32-bit uints down to depth values. */
399 GLuint shift = 0;
400 GLuint max = MAX_DEPTH;
401 while ((max&0x80000000)==0) {
402 max = max << 1;
403 shift++;
404 }
405 for (j=0;j<height;j++,y++) {
406 GLdepth zspan[MAX_WIDTH];
407 GLuint *zptr = (GLuint *) pixels + j * width;
408 for (i=0;i<width;i++) {
409 zspan[i] = zptr[i] >> shift;
410 }
411 gl_write_color_span( ctx, width, x, y, zspan,
412 red, green, blue, alpha, GL_BITMAP );
413 }
414 }
415 else {
416 /* General case (slower) */
417 GLuint i, j;
418
419 /* process image row by row */
420 for (i=0;i<height;i++,y++) {
421 GLfloat depth[MAX_WIDTH];
422 GLdepth zspan[MAX_WIDTH];
423
424 switch (type) {
425 case GL_UNSIGNED_BYTE:
426 {
427 GLubyte *src = (GLubyte *) pixels + i * width;
428 for (j=0;j<width;j++) {
429 depth[j] = UBYTE_TO_FLOAT( *src++ );
430 }
431 }
432 break;
433 case GL_BYTE:
434 {
435 GLbyte *src = (GLbyte *) pixels + i * width;
436 for (j=0;j<width;j++) {
437 depth[j] = BYTE_TO_FLOAT( *src++ );
438 }
439 }
440 break;
441 case GL_UNSIGNED_SHORT:
442 {
443 GLushort *src = (GLushort *) pixels + i * width;
444 for (j=0;j<width;j++) {
445 depth[j] = USHORT_TO_FLOAT( *src++ );
446 }
447 }
448 break;
449 case GL_SHORT:
450 {
451 GLshort *src = (GLshort *) pixels + i * width;
452 for (j=0;j<width;j++) {
453 depth[j] = SHORT_TO_FLOAT( *src++ );
454 }
455 }
456 break;
457 case GL_UNSIGNED_INT:
458 {
459 GLuint *src = (GLuint *) pixels + i * width;
460 for (j=0;j<width;j++) {
461 depth[j] = UINT_TO_FLOAT( *src++ );
462 }
463 }
464 break;
465 case GL_INT:
466 {
467 GLint *src = (GLint *) pixels + i * width;
468 for (j=0;j<width;j++) {
469 depth[j] = INT_TO_FLOAT( *src++ );
470 }
471 }
472 break;
473 case GL_FLOAT:
474 {
475 GLfloat *src = (GLfloat *) pixels + i * width;
476 for (j=0;j<width;j++) {
477 depth[j] = *src++;
478 }
479 }
480 break;
481 default:
482 gl_problem(ctx, "Bad type in draw_depth_pixels");
483 return;
484 }
485
486 /* apply depth scale and bias */
487 if (ctx->Pixel.DepthScale!=1.0 || ctx->Pixel.DepthBias!=0.0) {
488 for (j=0;j<width;j++) {
489 depth[j] = depth[j] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
490 }
491 }
492
493 /* clamp depth values to [0,1] and convert from floats to integers */
494 for (j=0;j<width;j++) {
495 zspan[j] = (GLdepth) (CLAMP( depth[j], 0.0F, 1.0F ) * DEPTH_SCALE);
496 }
497
498 if (ctx->Visual->RGBAflag) {
499 if (zoom) {
500 gl_write_zoomed_color_span( ctx, width, x, y, zspan,
501 red, green, blue, alpha, desty );
502 }
503 else {
504 gl_write_color_span( ctx, width, x, y, zspan,
505 red, green, blue, alpha, GL_BITMAP );
506 }
507 }
508 else {
509 if (zoom) {
510 gl_write_zoomed_index_span( ctx, width, x, y, zspan,
511 ispan, GL_BITMAP );
512 }
513 else {
514 gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
515 }
516 }
517
518 }
519 }
520 }
521
522
523
draw_color_pixels(GLcontext * ctx,GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels)524 static void draw_color_pixels(GLcontext* ctx, GLsizei width, GLsizei height,
525 GLenum format, GLenum type, const GLvoid *pixels)
526 {
527 GLuint i, j;
528 GLint x, y, desty;
529 GLdepth zspan[MAX_WIDTH];
530 GLboolean scale_or_bias, quick_draw;
531 GLboolean zoom;
532
533 zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
534
535 /* Position, depth of pixels */
536 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
537 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
538 desty = y;
539 if (ctx->Depth.Test)
540 {
541 /* fill in array of z values */
542 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
543 for (i = 0; i < width; i++)
544 {
545 zspan[i] = z;
546 }
547 }
548
549 /* Determine if scaling and/or biasing is needed */
550 if (ctx->Pixel.RedScale != 1.0F || ctx->Pixel.RedBias != 0.0F
551 || ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F
552 || ctx->Pixel.BlueScale != 1.0F || ctx->Pixel.BlueBias != 0.0F
553 || ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F)
554 {
555 scale_or_bias = GL_TRUE;
556 }
557 else
558 {
559 scale_or_bias = GL_FALSE;
560 }
561
562 /* Determine if we can directly call the device driver function */
563 if (ctx->RasterMask == 0 && !zoom && x >= 0 && y >= 0
564 && x + width <= ctx->Buffer->Width
565 && y + height <= ctx->Buffer->Height)
566 {
567 quick_draw = GL_TRUE;
568 }
569 else
570 {
571 quick_draw = GL_FALSE;
572 }
573
574 /* First check for common cases */
575 if (type == GL_UNSIGNED_BYTE
576 && (format == GL_RGB || format == GL_LUMINANCE || format == GL_BGR_EXT)
577 && !ctx->Pixel.MapColorFlag
578 && !scale_or_bias && ctx->Visual->EightBitColor)
579 {
580 DEFARRAY(GLubyte, alpha, MAX_WIDTH);
581 GLubyte *src = (GLubyte *) pixels;
582 /* constant alpha */
583 MEMSET(alpha, (GLint ) ctx->Visual->AlphaScale, width);
584 if (format == GL_RGB)
585 {
586 /* 8-bit RGB pixels */
587 DEFARRAY(GLubyte, red, MAX_WIDTH);
588 DEFARRAY(GLubyte, green, MAX_WIDTH);
589 DEFARRAY(GLubyte, blue, MAX_WIDTH);
590 for (i = 0; i < height; i++, y++)
591 {
592 for (j = 0; j < width; j++)
593 {
594 red[j] = *src++;
595 green[j] = *src++;
596 blue[j] = *src++;
597 }
598 if (quick_draw)
599 {
600 (*ctx->Driver.WriteColorSpan)(ctx, width, x, y, red, green,
601 blue, alpha, NULL);
602 }
603 else if (zoom)
604 {
605 gl_write_zoomed_color_span(ctx, (GLuint) width, x, y, zspan,
606 red, green, blue, alpha, desty);
607 }
608 else
609 {
610 gl_write_color_span(ctx, (GLuint) width, x, y, zspan, red,
611 green, blue, alpha, GL_BITMAP);
612 }
613 }
614 UNDEFARRAY( red );
615 UNDEFARRAY( green );
616 UNDEFARRAY( blue );
617 }
618 else if (format == GL_BGR_EXT)
619 {
620 /* 8-bit BGR pixels */
621 DEFARRAY(GLubyte, red, MAX_WIDTH);
622 DEFARRAY(GLubyte, green, MAX_WIDTH);
623 DEFARRAY(GLubyte, blue, MAX_WIDTH);
624 for (i = 0; i < height; i++, y++)
625 {
626 for (j = 0; j < width; j++)
627 {
628 blue[j] = *src++;
629 green[j] = *src++;
630 red[j] = *src++;
631 }
632 if (quick_draw)
633 {
634 (*ctx->Driver.WriteColorSpan)(ctx, width, x, y, red, green,
635 blue, alpha, NULL);
636 }
637 else if (zoom)
638 {
639 gl_write_zoomed_color_span(ctx, (GLuint) width, x, y, zspan,
640 red, green, blue, alpha, desty);
641 }
642 else
643 {
644 gl_write_color_span(ctx, (GLuint) width, x, y, zspan, red,
645 green, blue, alpha, GL_BITMAP);
646 }
647 }
648 UNDEFARRAY( red );
649 UNDEFARRAY( green );
650 UNDEFARRAY( blue );
651 }
652 else
653 {
654 /* 8-bit Luminance pixels */
655 GLubyte *lum = (GLubyte *) pixels;
656 for (i = 0; i < height; i++, y++, lum += width)
657 {
658 if (quick_draw)
659 {
660 (*ctx->Driver.WriteColorSpan)(ctx, width, x, y, lum, lum,
661 lum, alpha, NULL);
662 }
663 else if (zoom)
664 {
665 gl_write_zoomed_color_span(ctx, (GLuint) width, x, y, zspan,
666 lum, lum, lum, alpha, desty);
667 }
668 else
669 {
670 gl_write_color_span(ctx, (GLuint) width, x, y, zspan, lum,
671 lum, lum, alpha, GL_BITMAP);
672 }
673 }
674 }
675 UNDEFARRAY( alpha );
676 }
677 else
678 {
679 /* General solution */
680 GLboolean r_flag, g_flag, b_flag, a_flag, l_flag;
681 GLuint components;
682 GLboolean is_bgr;
683
684 r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE;
685 is_bgr = GL_FALSE;
686 switch (format)
687 {
688 case GL_RED:
689 r_flag = GL_TRUE;
690 components = 1;
691 break;
692 case GL_GREEN:
693 g_flag = GL_TRUE;
694 components = 1;
695 break;
696 case GL_BLUE:
697 b_flag = GL_TRUE;
698 components = 1;
699 break;
700 case GL_ALPHA:
701 a_flag = GL_TRUE;
702 components = 1;
703 break;
704 case GL_RGB:
705 r_flag = g_flag = b_flag = GL_TRUE;
706 components = 3;
707 break;
708 case GL_BGR_EXT:
709 is_bgr = GL_TRUE;
710 r_flag = g_flag = b_flag = GL_TRUE;
711 components = 3;
712 break;
713 case GL_LUMINANCE:
714 l_flag = GL_TRUE;
715 components = 1;
716 break;
717 case GL_LUMINANCE_ALPHA:
718 l_flag = a_flag = GL_TRUE;
719 components = 2;
720 break;
721 case GL_RGBA:
722 r_flag = g_flag = b_flag = a_flag = GL_TRUE;
723 components = 4;
724 break;
725 case GL_BGRA_EXT:
726 is_bgr = GL_TRUE;
727 r_flag = g_flag = b_flag = a_flag = GL_TRUE;
728 components = 4;
729 break;
730 default:
731 gl_problem(ctx, "Bad type in draw_color_pixels");
732 return;
733 }
734
735 /* process the image row by row */
736 for (i = 0; i < height; i++, y++)
737 {
738 DEFARRAY(GLfloat, rf, MAX_WIDTH);
739 DEFARRAY(GLfloat, gf, MAX_WIDTH);
740 DEFARRAY(GLfloat, bf, MAX_WIDTH);
741 DEFARRAY(GLfloat, af, MAX_WIDTH);
742 DEFARRAY(GLubyte, red, MAX_WIDTH);
743 DEFARRAY(GLubyte, green, MAX_WIDTH);
744 DEFARRAY(GLubyte, blue, MAX_WIDTH);
745 DEFARRAY(GLubyte, alpha, MAX_WIDTH);
746
747 /* convert to floats */
748 switch (type)
749 {
750 case GL_UNSIGNED_BYTE:
751 {
752 GLubyte *src = (GLubyte *) pixels + i * width * components;
753 for (j = 0; j < width; j++)
754 {
755 if (l_flag)
756 {
757 rf[j] = gf[j] = bf[j] = UBYTE_TO_FLOAT(*src++);
758 }
759 else if (is_bgr)
760 {
761 bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
762 gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
763 rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
764 }
765 else
766 {
767 rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
768 gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
769 bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
770 }
771 af[j] = a_flag ? UBYTE_TO_FLOAT(*src++) : 1.0;
772 }
773 }
774 break;
775 case GL_BYTE:
776 {
777 GLbyte *src = (GLbyte *) pixels + i * width * components;
778 for (j = 0; j < width; j++)
779 {
780 if (l_flag)
781 {
782 rf[j] = gf[j] = bf[j] = BYTE_TO_FLOAT(*src++);
783 }
784 else if (is_bgr)
785 {
786 bf[j] = b_flag ? BYTE_TO_FLOAT(*src++) : 0.0;
787 gf[j] = g_flag ? BYTE_TO_FLOAT(*src++) : 0.0;
788 rf[j] = r_flag ? BYTE_TO_FLOAT(*src++) : 0.0;
789 }
790 else
791 {
792 rf[j] = r_flag ? BYTE_TO_FLOAT(*src++) : 0.0;
793 gf[j] = g_flag ? BYTE_TO_FLOAT(*src++) : 0.0;
794 bf[j] = b_flag ? BYTE_TO_FLOAT(*src++) : 0.0;
795 }
796 af[j] = a_flag ? BYTE_TO_FLOAT(*src++) : 1.0;
797 }
798 }
799 break;
800 case GL_BITMAP:
801 /* special case */
802 break;
803 case GL_UNSIGNED_SHORT:
804 {
805 GLushort *src = (GLushort *) pixels + i * width * components;
806 for (j = 0; j < width; j++)
807 {
808 if (l_flag)
809 {
810 rf[j] = gf[j] = bf[j] = USHORT_TO_FLOAT(*src++);
811 }
812 else if (is_bgr)
813 {
814 bf[j] = b_flag ? USHORT_TO_FLOAT(*src++) : 0.0;
815 gf[j] = g_flag ? USHORT_TO_FLOAT(*src++) : 0.0;
816 rf[j] = r_flag ? USHORT_TO_FLOAT(*src++) : 0.0;
817 }
818 else
819 {
820 rf[j] = r_flag ? USHORT_TO_FLOAT(*src++) : 0.0;
821 gf[j] = g_flag ? USHORT_TO_FLOAT(*src++) : 0.0;
822 bf[j] = b_flag ? USHORT_TO_FLOAT(*src++) : 0.0;
823 }
824 af[j] = a_flag ? USHORT_TO_FLOAT(*src++) : 1.0;
825 }
826 }
827 break;
828 case GL_SHORT:
829 {
830 GLshort *src = (GLshort *) pixels + i * width * components;
831 for (j = 0; j < width; j++)
832 {
833 if (l_flag)
834 {
835 rf[j] = gf[j] = bf[j] = SHORT_TO_FLOAT(*src++);
836 }
837 else if (is_bgr)
838 {
839 bf[j] = b_flag ? SHORT_TO_FLOAT(*src++) : 0.0;
840 gf[j] = g_flag ? SHORT_TO_FLOAT(*src++) : 0.0;
841 rf[j] = r_flag ? SHORT_TO_FLOAT(*src++) : 0.0;
842 }
843 else
844 {
845 rf[j] = r_flag ? SHORT_TO_FLOAT(*src++) : 0.0;
846 gf[j] = g_flag ? SHORT_TO_FLOAT(*src++) : 0.0;
847 bf[j] = b_flag ? SHORT_TO_FLOAT(*src++) : 0.0;
848 }
849 af[j] = a_flag ? SHORT_TO_FLOAT(*src++) : 1.0;
850 }
851 }
852 break;
853 case GL_UNSIGNED_INT:
854 {
855 GLuint *src = (GLuint *) pixels + i * width * components;
856 for (j = 0; j < width; j++)
857 {
858 if (l_flag)
859 {
860 rf[j] = gf[j] = bf[j] = UINT_TO_FLOAT(*src++);
861 }
862 else if (is_bgr)
863 {
864 bf[j] = b_flag ? UINT_TO_FLOAT(*src++) : 0.0;
865 gf[j] = g_flag ? UINT_TO_FLOAT(*src++) : 0.0;
866 rf[j] = r_flag ? UINT_TO_FLOAT(*src++) : 0.0;
867 }
868 else
869 {
870 rf[j] = r_flag ? UINT_TO_FLOAT(*src++) : 0.0;
871 gf[j] = g_flag ? UINT_TO_FLOAT(*src++) : 0.0;
872 bf[j] = b_flag ? UINT_TO_FLOAT(*src++) : 0.0;
873 }
874 af[j] = a_flag ? UINT_TO_FLOAT(*src++) : 1.0;
875 }
876 }
877 break;
878 case GL_INT:
879 {
880 GLint *src = (GLint *) pixels + i * width * components;
881 for (j = 0; j < width; j++)
882 {
883 if (l_flag)
884 {
885 rf[j] = gf[j] = bf[j] = INT_TO_FLOAT(*src++);
886 }
887 else if (is_bgr)
888 {
889 bf[j] = b_flag ? INT_TO_FLOAT(*src++) : 0.0;
890 gf[j] = g_flag ? INT_TO_FLOAT(*src++) : 0.0;
891 rf[j] = r_flag ? INT_TO_FLOAT(*src++) : 0.0;
892 }
893 else
894 {
895 rf[j] = r_flag ? INT_TO_FLOAT(*src++) : 0.0;
896 gf[j] = g_flag ? INT_TO_FLOAT(*src++) : 0.0;
897 bf[j] = b_flag ? INT_TO_FLOAT(*src++) : 0.0;
898 }
899 af[j] = a_flag ? INT_TO_FLOAT(*src++) : 1.0;
900 }
901 }
902 break;
903 case GL_FLOAT:
904 {
905 GLfloat *src = (GLfloat *) pixels + i * width * components;
906 for (j = 0; j < width; j++)
907 {
908 if (l_flag)
909 {
910 rf[j] = gf[j] = bf[j] = *src++;
911 }
912 else if (is_bgr)
913 {
914 bf[j] = b_flag ? *src++ : 0.0;
915 gf[j] = g_flag ? *src++ : 0.0;
916 rf[j] = r_flag ? *src++ : 0.0;
917 }
918 else
919 {
920 rf[j] = r_flag ? *src++ : 0.0;
921 gf[j] = g_flag ? *src++ : 0.0;
922 bf[j] = b_flag ? *src++ : 0.0;
923 }
924 af[j] = a_flag ? *src++ : 1.0;
925 }
926 }
927 break;
928 default:
929 gl_error(ctx, GL_INVALID_ENUM, "glDrawPixels");
930 return;
931 }
932
933 /* apply scale and bias */
934 if (scale_or_bias)
935 {
936 for (j = 0; j < width; j++)
937 {
938 GLfloat r, g, b, a;
939 r = rf[j] * ctx->Pixel.RedScale + ctx->Pixel.RedBias;
940 g = gf[j] * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias;
941 b = bf[j] * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias;
942 a = af[j] * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias;
943 rf[j] = CLAMP(r, 0.0, 1.0);
944 gf[j] = CLAMP(g, 0.0, 1.0);
945 bf[j] = CLAMP(b, 0.0, 1.0);
946 af[j] = CLAMP(a, 0.0, 1.0);
947 }
948 }
949
950 /* apply pixel mappings */
951 if (ctx->Pixel.MapColorFlag)
952 {
953 GLfloat rscale = ctx->Pixel.MapRtoRsize - 1;
954 GLfloat gscale = ctx->Pixel.MapGtoGsize - 1;
955 GLfloat bscale = ctx->Pixel.MapBtoBsize - 1;
956 GLfloat ascale = ctx->Pixel.MapAtoAsize - 1;
957 for (j = 0; j < width; j++)
958 {
959 rf[j] = ctx->Pixel.MapRtoR[(GLint) (rf[j] * rscale)];
960 gf[j] = ctx->Pixel.MapGtoG[(GLint) (gf[j] * gscale)];
961 bf[j] = ctx->Pixel.MapBtoB[(GLint) (bf[j] * bscale)];
962 af[j] = ctx->Pixel.MapAtoA[(GLint) (af[j] * ascale)];
963 }
964 }
965
966 /* convert to integers */
967 for (j = 0; j < width; j++)
968 {
969 red[j] = (GLint) (rf[j] * ctx->Visual->RedScale);
970 green[j] = (GLint) (gf[j] * ctx->Visual->GreenScale);
971 blue[j] = (GLint) (bf[j] * ctx->Visual->BlueScale);
972 alpha[j] = (GLint) (af[j] * ctx->Visual->AlphaScale);
973 }
974
975 /* write to frame buffer */
976 if (quick_draw)
977 {
978 (*ctx->Driver.WriteColorSpan)(ctx, width, x, y, red, green,
979 blue, alpha, NULL);
980 }
981 else if (zoom)
982 {
983 gl_write_zoomed_color_span(ctx, width, x, y, zspan, red, green,
984 blue, alpha, desty);
985 }
986 else
987 {
988 gl_write_color_span(ctx, (GLuint) width, x, y, zspan, red,
989 green, blue, alpha, GL_BITMAP);
990 }
991
992 UNDEFARRAY(rf);
993 UNDEFARRAY(gf);
994 UNDEFARRAY(bf);
995 UNDEFARRAY(af);
996 UNDEFARRAY(red);
997 UNDEFARRAY(green);
998 UNDEFARRAY(blue);
999 UNDEFARRAY(alpha);
1000 }
1001 }
1002
1003 }
1004
1005
1006
1007 /*
1008 * Do a glDrawPixels( w, h, GL_RGB, GL_UNSIGNED_BYTE, pixels ) optimized
1009 * for the case of no pixel mapping, no scale, no bias, no zoom, default
1010 * storage mode, no raster ops, and no pixel clipping.
1011 * Return: GL_TRUE if success
1012 * GL_FALSE if conditions weren't met for optimized drawing
1013 */
quickdraw_rgb(GLcontext * ctx,GLsizei width,GLsizei height,const void * pixels)1014 static GLboolean quickdraw_rgb( GLcontext* ctx, GLsizei width, GLsizei height,
1015 const void *pixels )
1016 {
1017 DEFARRAY( GLubyte, red, MAX_WIDTH );
1018 DEFARRAY( GLubyte, green, MAX_WIDTH );
1019 DEFARRAY( GLubyte, blue, MAX_WIDTH );
1020 DEFARRAY( GLubyte, alpha, MAX_WIDTH );
1021 GLint i, j;
1022 GLint x, y;
1023 GLint bytes_per_row;
1024 GLboolean result;
1025
1026 bytes_per_row = width * 3 + (width % ctx->Unpack.Alignment);
1027
1028 if (!ctx->Current.RasterPosValid) {
1029 /* This is success, actually. */
1030 result = GL_TRUE;
1031 }
1032 else {
1033 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
1034 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
1035
1036 if (x<0 || y<0
1037 || x+width>ctx->Buffer->Width || y+height>ctx->Buffer->Height) {
1038 result = GL_FALSE; /* can't handle this situation */
1039 }
1040 else {
1041 /* constant alpha */
1042 for (j=0;j<width;j++) {
1043 alpha[j] = (GLint) ctx->Visual->AlphaScale;
1044 }
1045
1046 /* write directly to device driver */
1047 for (i=0;i<height;i++) {
1048 /* each row of pixel data starts at 4-byte boundary */
1049 GLubyte *src = (GLubyte *) pixels + i * bytes_per_row;
1050 for (j=0;j<width;j++) {
1051 red[j] = *src++;
1052 green[j] = *src++;
1053 blue[j] = *src++;
1054 }
1055 (*ctx->Driver.WriteColorSpan)( ctx, width, x, y+i,
1056 red, green, blue, alpha, NULL);
1057 }
1058 result = GL_TRUE;
1059 }
1060 }
1061
1062 UNDEFARRAY( red );
1063 UNDEFARRAY( green );
1064 UNDEFARRAY( blue );
1065 UNDEFARRAY( alpha );
1066
1067 return result;
1068 }
1069
1070
1071
1072 /*
1073 * Implements general glDrawPixels operation.
1074 */
drawpixels(GLcontext * ctx,GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels)1075 static void drawpixels( GLcontext* ctx, GLsizei width, GLsizei height,
1076 GLenum format, GLenum type, const GLvoid *pixels )
1077 {
1078 if (INSIDE_BEGIN_END(ctx)) {
1079 gl_error( ctx, GL_INVALID_OPERATION, "glDrawPixels" );
1080 return;
1081 }
1082
1083 if (ctx->RenderMode==GL_RENDER) {
1084 if (!ctx->Current.RasterPosValid) {
1085 return;
1086 }
1087 switch (format) {
1088 case GL_COLOR_INDEX:
1089 draw_index_pixels( ctx, width, height, type, pixels );
1090 break;
1091 case GL_STENCIL_INDEX:
1092 draw_stencil_pixels( ctx, width, height, type, pixels );
1093 break;
1094 case GL_DEPTH_COMPONENT:
1095 draw_depth_pixels( ctx, width, height, type, pixels );
1096 break;
1097 case GL_RED:
1098 case GL_GREEN:
1099 case GL_BLUE:
1100 case GL_ALPHA:
1101 case GL_RGB:
1102 case GL_BGR_EXT:
1103 case GL_LUMINANCE:
1104 case GL_LUMINANCE_ALPHA:
1105 case GL_RGBA:
1106 case GL_BGRA_EXT:
1107 draw_color_pixels( ctx, width, height, format, type, pixels );
1108 break;
1109 default:
1110 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels" );
1111 }
1112 }
1113 else if (ctx->RenderMode==GL_FEEDBACK) {
1114 if (ctx->Current.RasterPosValid) {
1115 GLfloat color[4], texcoord[4], invq;
1116 color[0] = ctx->Current.ByteColor[0] * ctx->Visual->InvRedScale;
1117 color[1] = ctx->Current.ByteColor[1] * ctx->Visual->InvGreenScale;
1118 color[2] = ctx->Current.ByteColor[2] * ctx->Visual->InvBlueScale;
1119 color[3] = ctx->Current.ByteColor[3] * ctx->Visual->InvAlphaScale;
1120 invq = 1.0F / ctx->Current.TexCoord[3];
1121 texcoord[0] = ctx->Current.TexCoord[0] * invq;
1122 texcoord[1] = ctx->Current.TexCoord[1] * invq;
1123 texcoord[2] = ctx->Current.TexCoord[2] * invq;
1124 texcoord[3] = ctx->Current.TexCoord[3];
1125 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
1126 gl_feedback_vertex( ctx, ctx->Current.RasterPos[0],
1127 ctx->Current.RasterPos[1],
1128 ctx->Current.RasterPos[2],
1129 ctx->Current.RasterPos[3],
1130 color, ctx->Current.Index, texcoord );
1131 }
1132 }
1133 else if (ctx->RenderMode==GL_SELECT) {
1134 if (ctx->Current.RasterPosValid) {
1135 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
1136 }
1137 }
1138 }
1139
1140
1141
1142 /*
1143 * Compile OR Execute a glDrawPixels!
1144 */
gl_DrawPixels(GLcontext * ctx,GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels)1145 void gl_DrawPixels( GLcontext* ctx, GLsizei width, GLsizei height,
1146 GLenum format, GLenum type, const GLvoid *pixels )
1147 {
1148 GLvoid *image;
1149
1150 if (width<0 || height<0) {
1151 gl_error( ctx, GL_INVALID_VALUE, "glDrawPixels" );
1152 return;
1153 }
1154
1155 if (ctx->NewState) {
1156 gl_update_state(ctx);
1157 }
1158
1159 /* Let the device driver take a crack at glDrawPixels */
1160 if (!ctx->CompileFlag && ctx->Driver.DrawPixels) {
1161 GLint x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
1162 GLint y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
1163 if ((*ctx->Driver.DrawPixels)( ctx, x, y, width, height,
1164 format, type, GL_FALSE, pixels )) {
1165 /* Device driver did the job */
1166 return;
1167 }
1168 }
1169
1170 if (format==GL_RGB && type==GL_UNSIGNED_BYTE && ctx->FastDrawPixels
1171 && !ctx->CompileFlag && ctx->RenderMode==GL_RENDER
1172 && ctx->RasterMask==0 && ctx->CallDepth==0) {
1173 /* optimized path */
1174 if (quickdraw_rgb( ctx, width, height, pixels )) {
1175 /* success */
1176 return;
1177 }
1178 }
1179
1180 /* take the general path */
1181
1182 /* THIS IS A REAL HACK - FIX IN MESA 2.5
1183 * If we're inside glCallList then we don't have to unpack the pixels again.
1184 */
1185 if (ctx->CallDepth == 0) {
1186 image = gl_unpack_pixels( ctx, width, height, format, type, pixels );
1187 if (!image) {
1188 gl_error( ctx, GL_OUT_OF_MEMORY, "glDrawPixels" );
1189 return;
1190 }
1191 }
1192 else {
1193 image = (GLvoid *) pixels;
1194 }
1195
1196 if (ctx->CompileFlag) {
1197 gl_save_DrawPixels( ctx, width, height, format, type, image );
1198 }
1199 if (ctx->ExecuteFlag) {
1200 drawpixels( ctx, width, height, format, type, image );
1201 if (!ctx->CompileFlag) {
1202 /* may discard unpacked image now */
1203 if (image!=pixels)
1204 free( image );
1205 }
1206 }
1207 }
1208