clean-up to reduce MSVC warnings
[mesa.git] / src / mesa / main / drawpix.c
1 /* $Id: drawpix.c,v 1.4 1999/10/19 20:33:57 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.1
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
29
30
31 #ifdef PC_HEADER
32 #include "all.h"
33 #else
34 #ifndef XFree86Server
35 #include <assert.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #else
39 #include "GL/xf86glx.h"
40 #endif
41 #include "context.h"
42 #include "drawpix.h"
43 #include "feedback.h"
44 #include "image.h"
45 #include "macros.h"
46 #include "mmath.h"
47 #include "pixel.h"
48 #include "span.h"
49 #include "stencil.h"
50 #include "types.h"
51 #include "zoom.h"
52 #ifdef XFree86Server
53 #include "GL/xf86glx.h"
54 #endif
55 #endif
56
57
58
59 /* TODO: apply texture mapping to fragments */
60
61
62 /*
63 * Try to do a fast glDrawPixels. Conditions include:
64 * not using a display list
65 * simple pixel unpacking
66 * no raster ops
67 * etc....
68 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
69 */
70 GLboolean gl_direct_DrawPixels( GLcontext *ctx,
71 const struct gl_pixelstore_attrib *unpack,
72 GLsizei width, GLsizei height,
73 GLenum format, GLenum type,
74 const GLvoid *pixels )
75 {
76 GLubyte rgb[MAX_WIDTH][3];
77 GLubyte rgba[MAX_WIDTH][4];
78
79 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glDrawPixels",
80 GL_FALSE);
81
82
83 if (!ctx->Current.RasterPosValid) {
84 /* no-op */
85 return GL_TRUE;
86 }
87
88 if (ctx->NewState) {
89 gl_update_state(ctx);
90 }
91
92 /* see if device driver can do the drawpix */
93 if (ctx->Driver.DrawPixels) {
94 GLint x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
95 GLint y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
96 if ((*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type,
97 unpack, pixels))
98 return GL_TRUE;
99 }
100
101 if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0
102 && ctx->Pixel.RedBias==0.0 && ctx->Pixel.RedScale==1.0
103 && ctx->Pixel.GreenBias==0.0 && ctx->Pixel.GreenScale==1.0
104 && ctx->Pixel.BlueBias==0.0 && ctx->Pixel.BlueScale==1.0
105 && ctx->Pixel.AlphaBias==0.0 && ctx->Pixel.AlphaScale==1.0
106 && ctx->Pixel.IndexShift==0 && ctx->Pixel.IndexOffset==0
107 && ctx->Pixel.MapColorFlag==0
108 && unpack->Alignment==1
109 && !unpack->SwapBytes
110 && !unpack->LsbFirst) {
111
112 GLint destX = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
113 GLint destY = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
114 GLint drawWidth = width; /* actual width drawn */
115 GLint drawHeight = height; /* actual height drawn */
116 GLint skipPixels = unpack->SkipPixels;
117 GLint skipRows = unpack->SkipRows;
118 GLint rowLength;
119 GLdepth zSpan[MAX_WIDTH]; /* only used when zooming */
120 GLint zoomY0;
121
122 if (unpack->RowLength > 0)
123 rowLength = unpack->RowLength;
124 else
125 rowLength = width;
126
127 /* If we're not using pixel zoom then do all clipping calculations
128 * now. Otherwise, we'll let the gl_write_zoomed_*_span() functions
129 * handle the clipping.
130 */
131 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
132 /* horizontal clipping */
133 if (destX < ctx->Buffer->Xmin) {
134 skipPixels += (ctx->Buffer->Xmin - destX);
135 drawWidth -= (ctx->Buffer->Xmin - destX);
136 destX = ctx->Buffer->Xmin;
137 }
138 if (destX + drawWidth > ctx->Buffer->Xmax)
139 drawWidth -= (destX + drawWidth - ctx->Buffer->Xmax - 1);
140 if (drawWidth <= 0)
141 return GL_TRUE;
142
143 /* vertical clipping */
144 if (destY < ctx->Buffer->Ymin) {
145 skipRows += (ctx->Buffer->Ymin - destY);
146 drawHeight -= (ctx->Buffer->Ymin - destY);
147 destY = ctx->Buffer->Ymin;
148 }
149 if (destY + drawHeight > ctx->Buffer->Ymax)
150 drawHeight -= (destY + drawHeight - ctx->Buffer->Ymax - 1);
151 if (drawHeight <= 0)
152 return GL_TRUE;
153 }
154 else {
155 /* setup array of fragment Z value to pass to zoom function */
156 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
157 GLint i;
158 assert(drawWidth < MAX_WIDTH);
159 for (i=0; i<drawWidth; i++)
160 zSpan[i] = z;
161
162 /* save Y value of first row */
163 zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
164 }
165
166
167 /*
168 * Ready to draw!
169 * The window region at (destX, destY) of size (drawWidth, drawHeight)
170 * will be written to.
171 * We'll take pixel data from buffer pointed to by "pixels" but we'll
172 * skip "skipRows" rows and skip "skipPixels" pixels/row.
173 */
174
175 if (format==GL_RGBA && type==GL_UNSIGNED_BYTE) {
176 if (ctx->Visual->RGBAflag) {
177 GLubyte *src = (GLubyte *) pixels
178 + (skipRows * rowLength + skipPixels) * 4;
179 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
180 /* no zooming */
181 GLint row;
182 for (row=0; row<drawHeight; row++) {
183 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
184 (void *) src, NULL);
185 src += rowLength * 4;
186 destY++;
187 }
188 }
189 else {
190 /* with zooming */
191 GLint row;
192 for (row=0; row<drawHeight; row++) {
193 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
194 zSpan, (void *) src, zoomY0);
195 src += rowLength * 4;
196 destY++;
197 }
198 }
199 }
200 return GL_TRUE;
201 }
202 else if (format==GL_RGB && type==GL_UNSIGNED_BYTE) {
203 if (ctx->Visual->RGBAflag) {
204 GLubyte *src = (GLubyte *) pixels
205 + (skipRows * rowLength + skipPixels) * 3;
206 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
207 GLint row;
208 for (row=0; row<drawHeight; row++) {
209 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
210 (void *) src, NULL);
211 src += rowLength * 3;
212 destY++;
213 }
214 }
215 else {
216 /* with zooming */
217 GLint row;
218 for (row=0; row<drawHeight; row++) {
219 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
220 zSpan, (void *) src, zoomY0);
221 src += rowLength * 3;
222 destY++;
223 }
224 }
225 }
226 return GL_TRUE;
227 }
228 else if (format==GL_LUMINANCE && type==GL_UNSIGNED_BYTE) {
229 if (ctx->Visual->RGBAflag) {
230 GLubyte *src = (GLubyte *) pixels
231 + (skipRows * rowLength + skipPixels);
232 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
233 /* no zooming */
234 GLint row;
235 assert(drawWidth < MAX_WIDTH);
236 for (row=0; row<drawHeight; row++) {
237 GLint i;
238 for (i=0;i<drawWidth;i++) {
239 rgb[i][0] = src[i];
240 rgb[i][1] = src[i];
241 rgb[i][2] = src[i];
242 }
243 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
244 (void *) rgb, NULL);
245 src += rowLength;
246 destY++;
247 }
248 }
249 else {
250 /* with zooming */
251 GLint row;
252 assert(drawWidth < MAX_WIDTH);
253 for (row=0; row<drawHeight; row++) {
254 GLint i;
255 for (i=0;i<drawWidth;i++) {
256 rgb[i][0] = src[i];
257 rgb[i][1] = src[i];
258 rgb[i][2] = src[i];
259 }
260 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
261 zSpan, (void *) rgb, zoomY0);
262 src += rowLength;
263 destY++;
264 }
265 }
266 }
267 return GL_TRUE;
268 }
269 else if (format==GL_LUMINANCE_ALPHA && type==GL_UNSIGNED_BYTE) {
270 if (ctx->Visual->RGBAflag) {
271 GLubyte *src = (GLubyte *) pixels
272 + (skipRows * rowLength + skipPixels)*2;
273 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
274 /* no zooming */
275 GLint row;
276 assert(drawWidth < MAX_WIDTH);
277 for (row=0; row<drawHeight; row++) {
278 GLint i;
279 GLubyte *ptr = src;
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 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
287 (void *) rgba, NULL);
288 src += rowLength*2;
289 destY++;
290 }
291 }
292 else {
293 /* with zooming */
294 GLint row;
295 assert(drawWidth < MAX_WIDTH);
296 for (row=0; row<drawHeight; row++) {
297 GLubyte *ptr = src;
298 GLint i;
299 for (i=0;i<drawWidth;i++) {
300 rgba[i][0] = *ptr;
301 rgba[i][1] = *ptr;
302 rgba[i][2] = *ptr++;
303 rgba[i][3] = *ptr++;
304 }
305 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
306 zSpan, (void *) rgba, zoomY0);
307 src += rowLength*2;
308 destY++;
309 }
310 }
311 }
312 return GL_TRUE;
313 }
314 else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
315 GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
316 if (ctx->Visual->RGBAflag) {
317 /* convert CI data to RGBA */
318 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
319 /* no zooming */
320 GLint row;
321 for (row=0; row<drawHeight; row++) {
322 assert(drawWidth < MAX_WIDTH);
323 gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
324 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
325 (const GLubyte (*)[4])rgba,
326 NULL);
327 src += rowLength;
328 destY++;
329 }
330 return GL_TRUE;
331 }
332 else {
333 /* with zooming */
334 GLint row;
335 for (row=0; row<drawHeight; row++) {
336 assert(drawWidth < MAX_WIDTH);
337 gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
338 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
339 zSpan, (void *) rgba, zoomY0);
340 src += rowLength;
341 destY++;
342 }
343 return GL_TRUE;
344 }
345 }
346 else {
347 /* write CI data to CI frame buffer */
348 GLint row;
349 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
350 /* no zooming */
351 for (row=0; row<drawHeight; row++) {
352 (*ctx->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY,
353 src, NULL);
354 src += rowLength;
355 destY++;
356 }
357 return GL_TRUE;
358 }
359 else {
360 /* with zooming */
361 return GL_FALSE;
362 }
363 }
364 }
365 else {
366 /* can't handle this pixel format and/or data type here */
367 return GL_FALSE;
368 }
369 }
370 else {
371 /* can't do direct render, have to use slow path */
372 return GL_FALSE;
373 }
374 }
375
376
377
378 /*
379 * Do glDrawPixels of index pixels.
380 */
381 static void draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
382 const struct gl_image *image )
383 {
384 GLint width, height, widthInBytes;
385 const GLint desty = y;
386 GLint i, j;
387 GLdepth zspan[MAX_WIDTH];
388 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
389
390 assert(image);
391 assert(image->Format == GL_COLOR_INDEX);
392
393 width = image->Width;
394 height = image->Height;
395 if (image->Type == GL_BITMAP)
396 widthInBytes = (width + 7) / 8;
397 else
398 widthInBytes = width;
399
400 /* Fragment depth values */
401 if (ctx->Depth.Test) {
402 GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
403 for (i=0;i<width;i++) {
404 zspan[i] = zval;
405 }
406 }
407
408 /* process the image row by row */
409 for (i=0;i<height;i++,y++) {
410 GLuint ispan[MAX_WIDTH];
411
412 /* convert to uints */
413 switch (image->Type) {
414 case GL_UNSIGNED_BYTE:
415 {
416 GLubyte *src = (GLubyte *) image->Data + i * width;
417 for (j=0;j<width;j++) {
418 ispan[j] = (GLuint) *src++;
419 }
420 }
421 break;
422 case GL_FLOAT:
423 {
424 GLfloat *src = (GLfloat *) image->Data + i * width;
425 for (j=0;j<width;j++) {
426 ispan[j] = (GLuint) (GLint) *src++;
427 }
428 }
429 break;
430 case GL_BITMAP:
431 {
432 GLubyte *src = (GLubyte *) image->Data + i * widthInBytes;
433 for (j=0;j<width;j++) {
434 ispan[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1;
435 }
436 }
437 break;
438 default:
439 gl_problem( ctx, "draw_index_pixels type" );
440 return;
441 }
442
443 /* apply shift and offset */
444 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
445 gl_shift_and_offset_ci( ctx, width, ispan );
446 }
447
448 if (ctx->Visual->RGBAflag) {
449 /* Convert index to RGBA and write to frame buffer */
450 GLubyte rgba[MAX_WIDTH][4];
451 gl_map_ci_to_rgba( ctx, width, ispan, rgba );
452 if (zoom) {
453 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
454 (const GLubyte (*)[4])rgba, desty );
455 }
456 else {
457 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
458 }
459 }
460 else {
461 /* optionally apply index map then write to frame buffer */
462 if (ctx->Pixel.MapColorFlag) {
463 gl_map_ci(ctx, width, ispan);
464 }
465 if (zoom) {
466 gl_write_zoomed_index_span( ctx, width, x, y, zspan, ispan, desty );
467 }
468 else {
469 gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
470 }
471 }
472 }
473
474 }
475
476
477
478 /*
479 * Do glDrawPixels of stencil image. The image datatype may either
480 * be GLubyte or GLbitmap.
481 */
482 static void draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
483 const struct gl_image *image )
484 {
485 GLint widthInBytes, width, height;
486 const GLint desty = y;
487 GLint i;
488 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
489
490 if (image->Type != GL_BYTE &&
491 image->Type != GL_UNSIGNED_BYTE &&
492 image->Type != GL_SHORT &&
493 image->Type != GL_UNSIGNED_SHORT &&
494 image->Type != GL_INT &&
495 image->Type != GL_UNSIGNED_INT &&
496 image->Type != GL_FLOAT &&
497 image->Type != GL_BITMAP) {
498 gl_error( ctx, GL_INVALID_OPERATION, "glDrawPixels(stencil type)");
499 return;
500 }
501
502 assert(image);
503 assert(image->Format == GL_STENCIL_INDEX);
504 assert(image->Type == GL_UNSIGNED_BYTE || image->Type == GL_BITMAP);
505
506 if (image->Type == GL_UNSIGNED_BYTE)
507 widthInBytes = image->Width;
508 else
509 widthInBytes = (image->Width + 7) / 8;
510 width = image->Width;
511 height = image->Height;
512
513 /* process the image row by row */
514 for (i=0;i<height;i++,y++) {
515 GLstencil *src = (GLstencil*)image->Data + i * widthInBytes;
516 GLstencil *stencilValues;
517 GLstencil stencilCopy[MAX_WIDTH];
518
519 if (image->Type == GL_BITMAP) {
520 /* convert bitmap data to GLubyte (0 or 1) data */
521 GLint j;
522 for (j = 0; j < width; j++) {
523 stencilCopy[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1;
524 }
525 src = stencilCopy;
526 }
527
528 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift
529 || ctx->Pixel.MapStencilFlag) {
530
531 /* make copy of stencil values */
532 if (src != stencilCopy)
533 MEMCPY( stencilCopy, src, width * sizeof(GLstencil));
534
535 /* apply shift and offset */
536 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
537 gl_shift_and_offset_stencil( ctx, width, stencilCopy );
538 }
539
540 /* mapping */
541 if (ctx->Pixel.MapStencilFlag) {
542 gl_map_stencil( ctx, width, stencilCopy );
543 }
544
545 stencilValues = stencilCopy;
546 }
547 else {
548 /* use stencil values in-place */
549 stencilValues = src;
550 }
551
552 /* write stencil values to stencil buffer */
553 if (zoom) {
554 gl_write_zoomed_stencil_span( ctx, (GLuint) width, x, y,
555 stencilValues, desty );
556 }
557 else {
558 gl_write_stencil_span( ctx, (GLuint) width, x, y, stencilValues );
559 }
560 }
561 }
562
563
564
565 /*
566 * Do a glDrawPixels of depth values.
567 */
568 static void draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
569 const struct gl_image *image )
570 {
571 GLint width, height;
572 const GLint desty = y;
573 GLubyte rgba[MAX_WIDTH][4];
574 GLuint ispan[MAX_WIDTH];
575 const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
576 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
577
578 assert(image);
579 assert(image->Format == GL_DEPTH_COMPONENT);
580
581 width = image->Width;
582 height = image->Height;
583
584 /* Color or index */
585 if (ctx->Visual->RGBAflag) {
586 GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F);
587 GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F);
588 GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F);
589 GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F);
590 GLint i;
591 for (i=0; i<width; i++) {
592 rgba[i][RCOMP] = r;
593 rgba[i][GCOMP] = g;
594 rgba[i][BCOMP] = b;
595 rgba[i][ACOMP] = a;
596 }
597 }
598 else {
599 GLint i;
600 for (i=0;i<width;i++) {
601 ispan[i] = ctx->Current.RasterIndex;
602 }
603 }
604
605 if (image->Type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
606 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
607 /* Special case: directly write 16-bit depth values */
608 GLint j;
609 for (j=0;j<height;j++,y++) {
610 GLdepth *zptr = (GLdepth *) image->Data + j * width;
611 gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
612 }
613 }
614 else if (image->Type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint)
615 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
616 /* Special case: directly write 32-bit depth values */
617 GLint i, j;
618 /* Compute shift value to scale 32-bit uints down to depth values. */
619 GLuint shift = 0;
620 GLuint max = MAX_DEPTH;
621 while ((max&0x80000000)==0) {
622 max = max << 1;
623 shift++;
624 }
625 for (j=0;j<height;j++,y++) {
626 GLdepth zspan[MAX_WIDTH];
627 GLuint *zptr = (GLuint *) image->Data + j * width;
628 for (i=0;i<width;i++) {
629 zspan[i] = zptr[i] >> shift;
630 }
631 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
632 }
633 }
634 else {
635 /* General case (slower) */
636 GLint i, j;
637
638 /* process image row by row */
639 for (i=0;i<height;i++,y++) {
640 GLfloat depth[MAX_WIDTH];
641 GLdepth zspan[MAX_WIDTH];
642
643 switch (image->Type) {
644 case GL_UNSIGNED_SHORT:
645 {
646 GLushort *src = (GLushort *) image->Data + i * width;
647 for (j=0;j<width;j++) {
648 depth[j] = USHORT_TO_FLOAT( *src++ );
649 }
650 }
651 break;
652 case GL_UNSIGNED_INT:
653 {
654 GLuint *src = (GLuint *) image->Data + i * width;
655 for (j=0;j<width;j++) {
656 depth[j] = UINT_TO_FLOAT( *src++ );
657 }
658 }
659 break;
660 case GL_FLOAT:
661 {
662 GLfloat *src = (GLfloat *) image->Data + i * width;
663 for (j=0;j<width;j++) {
664 depth[j] = *src++;
665 }
666 }
667 break;
668 default:
669 gl_problem(ctx, "Bad type in draw_depth_pixels");
670 return;
671 }
672
673 /* apply depth scale and bias */
674 if (ctx->Pixel.DepthScale!=1.0 || ctx->Pixel.DepthBias!=0.0) {
675 for (j=0;j<width;j++) {
676 depth[j] = depth[j] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
677 }
678 }
679
680 /* clamp depth values to [0,1] and convert from floats to integers */
681 for (j=0;j<width;j++) {
682 zspan[j] = (GLdepth) (CLAMP( depth[j], 0.0F, 1.0F ) * DEPTH_SCALE);
683 }
684
685 if (ctx->Visual->RGBAflag) {
686 if (zoom) {
687 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
688 (const GLubyte (*)[4])rgba, desty );
689 }
690 else {
691 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
692 }
693 }
694 else {
695 if (zoom) {
696 gl_write_zoomed_index_span( ctx, width, x, y, zspan,
697 ispan, GL_BITMAP );
698 }
699 else {
700 gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
701 }
702 }
703
704 }
705 }
706 }
707
708
709
710 /* Simple unpacking parameters: */
711 static struct gl_pixelstore_attrib NoUnpack = {
712 1, /* Alignment */
713 0, /* RowLength */
714 0, /* SkipPixels */
715 0, /* SkipRows */
716 0, /* ImageHeight */
717 0, /* SkipImages */
718 GL_FALSE, /* SwapBytes */
719 GL_FALSE /* LsbFirst */
720 };
721
722
723 /*
724 * Do glDrawPixels of RGBA pixels.
725 */
726 static void draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
727 const struct gl_image *image )
728 {
729 GLint width, height;
730 GLint i, j;
731 const GLint desty = y;
732 GLdepth zspan[MAX_WIDTH];
733 GLboolean quickDraw;
734 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
735
736 assert(image);
737
738 /* Try an optimized glDrawPixels first */
739 if (gl_direct_DrawPixels(ctx, &NoUnpack, image->Width, image->Height,
740 image->Format, image->Type, image->Data ))
741 return;
742
743 width = image->Width;
744 height = image->Height;
745
746 /* Fragment depth values */
747 if (ctx->Depth.Test) {
748 /* fill in array of z values */
749 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
750 for (i=0;i<width;i++) {
751 zspan[i] = z;
752 }
753 }
754
755 if (ctx->RasterMask==0 && !zoom && x>=0 && y>=0
756 && x+width<=ctx->Buffer->Width && y+height<=ctx->Buffer->Height) {
757 quickDraw = GL_TRUE;
758 }
759 else {
760 quickDraw = GL_FALSE;
761 }
762
763 {
764 /* General solution */
765 GLboolean r_flag, g_flag, b_flag, a_flag, l_flag;
766 GLuint components;
767 GLubyte rgba[MAX_WIDTH][4];
768 GLfloat rf[MAX_WIDTH];
769 GLfloat gf[MAX_WIDTH];
770 GLfloat bf[MAX_WIDTH];
771 DEFARRAY(GLfloat,af,MAX_WIDTH);
772 CHECKARRAY(af,return);
773
774 r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE;
775 switch (image->Format) {
776 case GL_RED:
777 r_flag = GL_TRUE;
778 components = 1;
779 break;
780 case GL_GREEN:
781 g_flag = GL_TRUE;
782 components = 1;
783 break;
784 case GL_BLUE:
785 b_flag = GL_TRUE;
786 components = 1;
787 break;
788 case GL_ALPHA:
789 a_flag = GL_TRUE;
790 components = 1;
791 break;
792 case GL_RGB:
793 r_flag = g_flag = b_flag = GL_TRUE;
794 components = 3;
795 break;
796 case GL_LUMINANCE:
797 l_flag = GL_TRUE;
798 components = 1;
799 break;
800 case GL_LUMINANCE_ALPHA:
801 l_flag = a_flag = GL_TRUE;
802 components = 2;
803 break;
804 case GL_RGBA:
805 r_flag = g_flag = b_flag = a_flag = GL_TRUE;
806 components = 4;
807 break;
808 default:
809 gl_problem(ctx, "Bad type in draw_rgba_pixels");
810 goto cleanup;
811 }
812
813 /* process the image row by row */
814 for (i=0;i<height;i++,y++) {
815 /* convert to floats */
816 switch (image->Type) {
817 case GL_UNSIGNED_BYTE:
818 {
819 GLubyte *src = (GLubyte *) image->Data + i * width * components;
820 for (j=0;j<width;j++) {
821 if (l_flag) {
822 rf[j] = gf[j] = bf[j] = UBYTE_TO_FLOAT(*src++);
823 }
824 else {
825 rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
826 gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
827 bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
828 }
829 af[j] = a_flag ? UBYTE_TO_FLOAT(*src++) : 1.0;
830 }
831 }
832 break;
833 case GL_FLOAT:
834 {
835 GLfloat *src = (GLfloat *) image->Data + i * width * components;
836 for (j=0;j<width;j++) {
837 if (l_flag) {
838 rf[j] = gf[j] = bf[j] = *src++;
839 }
840 else {
841 rf[j] = r_flag ? *src++ : 0.0;
842 gf[j] = g_flag ? *src++ : 0.0;
843 bf[j] = b_flag ? *src++ : 0.0;
844 }
845 af[j] = a_flag ? *src++ : 1.0;
846 }
847 }
848 break;
849 default:
850 gl_problem( ctx, "draw_rgba_pixels type" );
851 goto cleanup;
852 }
853
854 /* apply scale and bias */
855 if (ctx->Pixel.ScaleOrBiasRGBA) {
856 gl_scale_and_bias_color(ctx, width, rf, gf, bf, af);
857 }
858
859 /* apply pixel mappings */
860 if (ctx->Pixel.MapColorFlag) {
861 gl_map_color(ctx, width, rf, gf, bf, af);
862 }
863
864 /* convert to integers */
865 for (j=0;j<width;j++) {
866 rgba[j][RCOMP] = (GLint) (rf[j] * 255.0F);
867 rgba[j][GCOMP] = (GLint) (gf[j] * 255.0F);
868 rgba[j][BCOMP] = (GLint) (bf[j] * 255.0F);
869 rgba[j][ACOMP] = (GLint) (af[j] * 255.0F);
870 }
871
872 /* write to frame buffer */
873 if (quickDraw) {
874 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y,
875 (const GLubyte (*)[4])rgba, NULL);
876 }
877 else if (zoom) {
878 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
879 (const GLubyte (*)[4])rgba, desty );
880 }
881 else {
882 gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP);
883 }
884 }
885 cleanup:
886 UNDEFARRAY(af);
887 }
888 }
889
890
891
892 /*
893 * Execute glDrawPixels
894 */
895 void gl_DrawPixels( GLcontext* ctx, struct gl_image *image )
896 {
897 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels");
898
899
900 if (gl_image_error_test( ctx, image, "glDrawPixels" ))
901 return;
902
903 if (ctx->RenderMode==GL_RENDER) {
904 GLint x, y;
905 if (!ctx->Current.RasterPosValid) {
906 return;
907 }
908
909 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
910 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
911
912 switch (image->Format) {
913 case GL_COLOR_INDEX:
914 draw_index_pixels( ctx, x, y, image );
915 break;
916 case GL_STENCIL_INDEX:
917 draw_stencil_pixels( ctx, x, y, image );
918 break;
919 case GL_DEPTH_COMPONENT:
920 draw_depth_pixels( ctx, x, y, image );
921 break;
922 case GL_RED:
923 case GL_GREEN:
924 case GL_BLUE:
925 case GL_ALPHA:
926 case GL_RGB:
927 case GL_LUMINANCE:
928 case GL_LUMINANCE_ALPHA:
929 case GL_RGBA:
930 draw_rgba_pixels( ctx, x, y, image );
931 break;
932 default:
933 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels" );
934 return;
935 }
936 }
937 else if (ctx->RenderMode==GL_FEEDBACK) {
938 if (ctx->Current.RasterPosValid) {
939 GLfloat color[4];
940 GLfloat texcoord[4], invq;
941 UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor);
942 invq = 1.0F / ctx->Current.Texcoord[0][3];
943 texcoord[0] = ctx->Current.Texcoord[0][0] * invq;
944 texcoord[1] = ctx->Current.Texcoord[0][1] * invq;
945 texcoord[2] = ctx->Current.Texcoord[0][2] * invq;
946 texcoord[3] = ctx->Current.Texcoord[0][3];
947 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
948 gl_feedback_vertex( ctx,
949 ctx->Current.RasterPos,
950 color, ctx->Current.Index, texcoord );
951 }
952 }
953 else if (ctx->RenderMode==GL_SELECT) {
954 if (ctx->Current.RasterPosValid) {
955 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
956 }
957 }
958 }
959