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