02016d15154b0e0ea16157d71dde41830f22ffff
[mesa.git] / src / mesa / main / drawpix.c
1 /* $Id: drawpix.c,v 1.3 1999/10/08 09:27:10 keithw 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 assert(image);
491 assert(image->Format == GL_STENCIL_INDEX);
492 assert(image->Type == GL_UNSIGNED_BYTE || image->Type == GL_BITMAP);
493
494 if (image->Type == GL_UNSIGNED_BYTE)
495 widthInBytes = image->Width;
496 else
497 widthInBytes = (image->Width + 7) / 8;
498 width = image->Width;
499 height = image->Height;
500
501 /* process the image row by row */
502 for (i=0;i<height;i++,y++) {
503 GLstencil *src = (GLstencil*)image->Data + i * widthInBytes;
504 GLstencil *stencilValues;
505 GLstencil stencilCopy[MAX_WIDTH];
506
507 if (image->Type == GL_BITMAP) {
508 /* convert bitmap data to GLubyte (0 or 1) data */
509 GLint j;
510 for (j = 0; j < width; j++) {
511 stencilCopy[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1;
512 }
513 src = stencilCopy;
514 }
515
516 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift
517 || ctx->Pixel.MapStencilFlag) {
518
519 /* make copy of stencil values */
520 if (src != stencilCopy)
521 MEMCPY( stencilCopy, src, width * sizeof(GLstencil));
522
523 /* apply shift and offset */
524 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
525 gl_shift_and_offset_stencil( ctx, width, stencilCopy );
526 }
527
528 /* mapping */
529 if (ctx->Pixel.MapStencilFlag) {
530 gl_map_stencil( ctx, width, stencilCopy );
531 }
532
533 stencilValues = stencilCopy;
534 }
535 else {
536 /* use stencil values in-place */
537 stencilValues = src;
538 }
539
540 /* write stencil values to stencil buffer */
541 if (zoom) {
542 gl_write_zoomed_stencil_span( ctx, (GLuint) width, x, y,
543 stencilValues, desty );
544 }
545 else {
546 gl_write_stencil_span( ctx, (GLuint) width, x, y, stencilValues );
547 }
548 }
549 }
550
551
552
553 /*
554 * Do a glDrawPixels of depth values.
555 */
556 static void draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
557 const struct gl_image *image )
558 {
559 GLint width, height;
560 const GLint desty = y;
561 GLubyte rgba[MAX_WIDTH][4];
562 GLuint ispan[MAX_WIDTH];
563 const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
564 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
565
566 assert(image);
567 assert(image->Format == GL_DEPTH_COMPONENT);
568
569 width = image->Width;
570 height = image->Height;
571
572 /* Color or index */
573 if (ctx->Visual->RGBAflag) {
574 GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F);
575 GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F);
576 GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F);
577 GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F);
578 GLint i;
579 for (i=0; i<width; i++) {
580 rgba[i][RCOMP] = r;
581 rgba[i][GCOMP] = g;
582 rgba[i][BCOMP] = b;
583 rgba[i][ACOMP] = a;
584 }
585 }
586 else {
587 GLint i;
588 for (i=0;i<width;i++) {
589 ispan[i] = ctx->Current.RasterIndex;
590 }
591 }
592
593 if (image->Type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
594 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
595 /* Special case: directly write 16-bit depth values */
596 GLint j;
597 for (j=0;j<height;j++,y++) {
598 GLdepth *zptr = (GLdepth *) image->Data + j * width;
599 gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
600 }
601 }
602 else if (image->Type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint)
603 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
604 /* Special case: directly write 32-bit depth values */
605 GLint i, j;
606 /* Compute shift value to scale 32-bit uints down to depth values. */
607 GLuint shift = 0;
608 GLuint max = MAX_DEPTH;
609 while ((max&0x80000000)==0) {
610 max = max << 1;
611 shift++;
612 }
613 for (j=0;j<height;j++,y++) {
614 GLdepth zspan[MAX_WIDTH];
615 GLuint *zptr = (GLuint *) image->Data + j * width;
616 for (i=0;i<width;i++) {
617 zspan[i] = zptr[i] >> shift;
618 }
619 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
620 }
621 }
622 else {
623 /* General case (slower) */
624 GLint i, j;
625
626 /* process image row by row */
627 for (i=0;i<height;i++,y++) {
628 GLfloat depth[MAX_WIDTH];
629 GLdepth zspan[MAX_WIDTH];
630
631 switch (image->Type) {
632 case GL_UNSIGNED_SHORT:
633 {
634 GLushort *src = (GLushort *) image->Data + i * width;
635 for (j=0;j<width;j++) {
636 depth[j] = USHORT_TO_FLOAT( *src++ );
637 }
638 }
639 break;
640 case GL_UNSIGNED_INT:
641 {
642 GLuint *src = (GLuint *) image->Data + i * width;
643 for (j=0;j<width;j++) {
644 depth[j] = UINT_TO_FLOAT( *src++ );
645 }
646 }
647 break;
648 case GL_FLOAT:
649 {
650 GLfloat *src = (GLfloat *) image->Data + i * width;
651 for (j=0;j<width;j++) {
652 depth[j] = *src++;
653 }
654 }
655 break;
656 default:
657 gl_problem(ctx, "Bad type in draw_depth_pixels");
658 return;
659 }
660
661 /* apply depth scale and bias */
662 if (ctx->Pixel.DepthScale!=1.0 || ctx->Pixel.DepthBias!=0.0) {
663 for (j=0;j<width;j++) {
664 depth[j] = depth[j] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
665 }
666 }
667
668 /* clamp depth values to [0,1] and convert from floats to integers */
669 for (j=0;j<width;j++) {
670 zspan[j] = (GLdepth) (CLAMP( depth[j], 0.0F, 1.0F ) * DEPTH_SCALE);
671 }
672
673 if (ctx->Visual->RGBAflag) {
674 if (zoom) {
675 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
676 (const GLubyte (*)[4])rgba, desty );
677 }
678 else {
679 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
680 }
681 }
682 else {
683 if (zoom) {
684 gl_write_zoomed_index_span( ctx, width, x, y, zspan,
685 ispan, GL_BITMAP );
686 }
687 else {
688 gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
689 }
690 }
691
692 }
693 }
694 }
695
696
697
698 /* Simple unpacking parameters: */
699 static struct gl_pixelstore_attrib NoUnpack = {
700 1, /* Alignment */
701 0, /* RowLength */
702 0, /* SkipPixels */
703 0, /* SkipRows */
704 0, /* ImageHeight */
705 0, /* SkipImages */
706 GL_FALSE, /* SwapBytes */
707 GL_FALSE /* LsbFirst */
708 };
709
710
711 /*
712 * Do glDrawPixels of RGBA pixels.
713 */
714 static void draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
715 const struct gl_image *image )
716 {
717 GLint width, height;
718 GLint i, j;
719 const GLint desty = y;
720 GLdepth zspan[MAX_WIDTH];
721 GLboolean quickDraw;
722 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
723
724 assert(image);
725
726 /* Try an optimized glDrawPixels first */
727 if (gl_direct_DrawPixels(ctx, &NoUnpack, image->Width, image->Height,
728 image->Format, image->Type, image->Data ))
729 return;
730
731 width = image->Width;
732 height = image->Height;
733
734 /* Fragment depth values */
735 if (ctx->Depth.Test) {
736 /* fill in array of z values */
737 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
738 for (i=0;i<width;i++) {
739 zspan[i] = z;
740 }
741 }
742
743 if (ctx->RasterMask==0 && !zoom && x>=0 && y>=0
744 && x+width<=ctx->Buffer->Width && y+height<=ctx->Buffer->Height) {
745 quickDraw = GL_TRUE;
746 }
747 else {
748 quickDraw = GL_FALSE;
749 }
750
751 {
752 /* General solution */
753 GLboolean r_flag, g_flag, b_flag, a_flag, l_flag;
754 GLuint components;
755 GLubyte rgba[MAX_WIDTH][4];
756 GLfloat rf[MAX_WIDTH];
757 GLfloat gf[MAX_WIDTH];
758 GLfloat bf[MAX_WIDTH];
759 DEFARRAY(GLfloat,af,MAX_WIDTH);
760 CHECKARRAY(af,return);
761
762 r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE;
763 switch (image->Format) {
764 case GL_RED:
765 r_flag = GL_TRUE;
766 components = 1;
767 break;
768 case GL_GREEN:
769 g_flag = GL_TRUE;
770 components = 1;
771 break;
772 case GL_BLUE:
773 b_flag = GL_TRUE;
774 components = 1;
775 break;
776 case GL_ALPHA:
777 a_flag = GL_TRUE;
778 components = 1;
779 break;
780 case GL_RGB:
781 r_flag = g_flag = b_flag = GL_TRUE;
782 components = 3;
783 break;
784 case GL_LUMINANCE:
785 l_flag = GL_TRUE;
786 components = 1;
787 break;
788 case GL_LUMINANCE_ALPHA:
789 l_flag = a_flag = GL_TRUE;
790 components = 2;
791 break;
792 case GL_RGBA:
793 r_flag = g_flag = b_flag = a_flag = GL_TRUE;
794 components = 4;
795 break;
796 default:
797 gl_problem(ctx, "Bad type in draw_rgba_pixels");
798 goto cleanup;
799 }
800
801 /* process the image row by row */
802 for (i=0;i<height;i++,y++) {
803 /* convert to floats */
804 switch (image->Type) {
805 case GL_UNSIGNED_BYTE:
806 {
807 GLubyte *src = (GLubyte *) image->Data + i * width * components;
808 for (j=0;j<width;j++) {
809 if (l_flag) {
810 rf[j] = gf[j] = bf[j] = UBYTE_TO_FLOAT(*src++);
811 }
812 else {
813 rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
814 gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
815 bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
816 }
817 af[j] = a_flag ? UBYTE_TO_FLOAT(*src++) : 1.0;
818 }
819 }
820 break;
821 case GL_FLOAT:
822 {
823 GLfloat *src = (GLfloat *) image->Data + i * width * components;
824 for (j=0;j<width;j++) {
825 if (l_flag) {
826 rf[j] = gf[j] = bf[j] = *src++;
827 }
828 else {
829 rf[j] = r_flag ? *src++ : 0.0;
830 gf[j] = g_flag ? *src++ : 0.0;
831 bf[j] = b_flag ? *src++ : 0.0;
832 }
833 af[j] = a_flag ? *src++ : 1.0;
834 }
835 }
836 break;
837 default:
838 gl_problem( ctx, "draw_rgba_pixels type" );
839 goto cleanup;
840 }
841
842 /* apply scale and bias */
843 if (ctx->Pixel.ScaleOrBiasRGBA) {
844 gl_scale_and_bias_color(ctx, width, rf, gf, bf, af);
845 }
846
847 /* apply pixel mappings */
848 if (ctx->Pixel.MapColorFlag) {
849 gl_map_color(ctx, width, rf, gf, bf, af);
850 }
851
852 /* convert to integers */
853 for (j=0;j<width;j++) {
854 rgba[j][RCOMP] = (GLint) (rf[j] * 255.0F);
855 rgba[j][GCOMP] = (GLint) (gf[j] * 255.0F);
856 rgba[j][BCOMP] = (GLint) (bf[j] * 255.0F);
857 rgba[j][ACOMP] = (GLint) (af[j] * 255.0F);
858 }
859
860 /* write to frame buffer */
861 if (quickDraw) {
862 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y,
863 (const GLubyte (*)[4])rgba, NULL);
864 }
865 else if (zoom) {
866 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
867 (const GLubyte (*)[4])rgba, desty );
868 }
869 else {
870 gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP);
871 }
872 }
873 cleanup:
874 UNDEFARRAY(af);
875 }
876 }
877
878
879
880 /*
881 * Execute glDrawPixels
882 */
883 void gl_DrawPixels( GLcontext* ctx, struct gl_image *image )
884 {
885 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels");
886
887
888 if (gl_image_error_test( ctx, image, "glDrawPixels" ))
889 return;
890
891 if (ctx->RenderMode==GL_RENDER) {
892 GLint x, y;
893 if (!ctx->Current.RasterPosValid) {
894 return;
895 }
896
897 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
898 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
899
900 switch (image->Format) {
901 case GL_COLOR_INDEX:
902 draw_index_pixels( ctx, x, y, image );
903 break;
904 case GL_STENCIL_INDEX:
905 draw_stencil_pixels( ctx, x, y, image );
906 break;
907 case GL_DEPTH_COMPONENT:
908 draw_depth_pixels( ctx, x, y, image );
909 break;
910 case GL_RED:
911 case GL_GREEN:
912 case GL_BLUE:
913 case GL_ALPHA:
914 case GL_RGB:
915 case GL_LUMINANCE:
916 case GL_LUMINANCE_ALPHA:
917 case GL_RGBA:
918 draw_rgba_pixels( ctx, x, y, image );
919 break;
920 default:
921 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels" );
922 return;
923 }
924 }
925 else if (ctx->RenderMode==GL_FEEDBACK) {
926 if (ctx->Current.RasterPosValid) {
927 GLfloat color[4];
928 GLfloat texcoord[4], invq;
929 UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor);
930 invq = 1.0F / ctx->Current.Texcoord[0][3];
931 texcoord[0] = ctx->Current.Texcoord[0][0] * invq;
932 texcoord[1] = ctx->Current.Texcoord[0][1] * invq;
933 texcoord[2] = ctx->Current.Texcoord[0][2] * invq;
934 texcoord[3] = ctx->Current.Texcoord[0][3];
935 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
936 gl_feedback_vertex( ctx,
937 ctx->Current.RasterPos,
938 color, ctx->Current.Index, texcoord );
939 }
940 }
941 else if (ctx->RenderMode==GL_SELECT) {
942 if (ctx->Current.RasterPosValid) {
943 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
944 }
945 }
946 }
947