source: trunk/src/opengl/mesa/drawpix.c@ 2962

Last change on this file since 2962 was 2962, checked in by jeroen, 25 years ago

* empty log message *

File size: 29.7 KB
Line 
1/* $Id: drawpix.c,v 1.2 2000-03-01 18:49:27 jeroen 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 "types.h"
42#include "context.h"
43#include "drawpix.h"
44#include "feedback.h"
45#include "image.h"
46#include "macros.h"
47#include "mmath.h"
48#include "pixel.h"
49#include "span.h"
50#include "stencil.h"
51#include "zoom.h"
52#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 (const GLubyte (*)[4])src,
182 NULL);
183 src += rowLength * 4;
184 destY++;
185 }
186 }
187 else {
188 /* with zooming */
189 GLint row;
190 for (row=0; row<drawHeight; row++) {
191 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
192 zSpan,
193 (const GLubyte (*)[4]) src,
194 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 (const GLubyte (*)[3]) src,
211 NULL);
212 src += rowLength * 3;
213 destY++;
214 }
215 }
216 else {
217 /* with zooming */
218 GLint row;
219 for (row=0; row<drawHeight; row++) {
220 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
221 zSpan,
222 (const GLubyte (*)[3]) src,
223 zoomY0);
224 src += rowLength * 3;
225 destY++;
226 }
227 }
228 }
229 return GL_TRUE;
230 }
231 else if (format==GL_LUMINANCE && type==GL_UNSIGNED_BYTE) {
232 if (ctx->Visual->RGBAflag) {
233 GLubyte *src = (GLubyte *) pixels
234 + (skipRows * rowLength + skipPixels);
235 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
236 /* no zooming */
237 GLint row;
238 assert(drawWidth < MAX_WIDTH);
239 for (row=0; row<drawHeight; row++) {
240 GLint i;
241 for (i=0;i<drawWidth;i++) {
242 rgb[i][0] = src[i];
243 rgb[i][1] = src[i];
244 rgb[i][2] = src[i];
245 }
246 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
247 (const GLubyte (*)[3]) rgb,
248 NULL);
249 src += rowLength;
250 destY++;
251 }
252 }
253 else {
254 /* with zooming */
255 GLint row;
256 assert(drawWidth < MAX_WIDTH);
257 for (row=0; row<drawHeight; row++) {
258 GLint i;
259 for (i=0;i<drawWidth;i++) {
260 rgb[i][0] = src[i];
261 rgb[i][1] = src[i];
262 rgb[i][2] = src[i];
263 }
264 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
265 zSpan,
266 (const GLubyte (*)[3]) rgb,
267 zoomY0);
268 src += rowLength;
269 destY++;
270 }
271 }
272 }
273 return GL_TRUE;
274 }
275 else if (format==GL_LUMINANCE_ALPHA && type==GL_UNSIGNED_BYTE) {
276 if (ctx->Visual->RGBAflag) {
277 GLubyte *src = (GLubyte *) pixels
278 + (skipRows * rowLength + skipPixels)*2;
279 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
280 /* no zooming */
281 GLint row;
282 assert(drawWidth < MAX_WIDTH);
283 for (row=0; row<drawHeight; row++) {
284 GLint i;
285 GLubyte *ptr = src;
286 for (i=0;i<drawWidth;i++) {
287 rgba[i][0] = *ptr;
288 rgba[i][1] = *ptr;
289 rgba[i][2] = *ptr++;
290 rgba[i][3] = *ptr++;
291 }
292 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
293 (const GLubyte (*)[4]) rgba,
294 NULL);
295 src += rowLength*2;
296 destY++;
297 }
298 }
299 else {
300 /* with zooming */
301 GLint row;
302 assert(drawWidth < MAX_WIDTH);
303 for (row=0; row<drawHeight; row++) {
304 GLubyte *ptr = src;
305 GLint i;
306 for (i=0;i<drawWidth;i++) {
307 rgba[i][0] = *ptr;
308 rgba[i][1] = *ptr;
309 rgba[i][2] = *ptr++;
310 rgba[i][3] = *ptr++;
311 }
312 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
313 zSpan,
314 (const GLubyte (*)[4]) rgba,
315 zoomY0);
316 src += rowLength*2;
317 destY++;
318 }
319 }
320 }
321 return GL_TRUE;
322 }
323 else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
324 GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
325 if (ctx->Visual->RGBAflag) {
326 /* convert CI data to RGBA */
327 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
328 /* no zooming */
329 GLint row;
330 for (row=0; row<drawHeight; row++) {
331 assert(drawWidth < MAX_WIDTH);
332 gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
333 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
334 (const GLubyte (*)[4])rgba,
335 NULL);
336 src += rowLength;
337 destY++;
338 }
339 return GL_TRUE;
340 }
341 else {
342 /* with zooming */
343 GLint row;
344 for (row=0; row<drawHeight; row++) {
345 assert(drawWidth < MAX_WIDTH);
346 gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
347 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
348 zSpan,
349 (const GLubyte (*)[4]) rgba,
350 zoomY0);
351 src += rowLength;
352 destY++;
353 }
354 return GL_TRUE;
355 }
356 }
357 else {
358 /* write CI data to CI frame buffer */
359 GLint row;
360 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
361 /* no zooming */
362 for (row=0; row<drawHeight; row++) {
363 (*ctx->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY,
364 src, NULL);
365 src += rowLength;
366 destY++;
367 }
368 return GL_TRUE;
369 }
370 else {
371 /* with zooming */
372 return GL_FALSE;
373 }
374 }
375 }
376 else {
377 /* can't handle this pixel format and/or data type here */
378 return GL_FALSE;
379 }
380 }
381 else {
382 /* can't do direct render, have to use slow path */
383 return GL_FALSE;
384 }
385}
386
387
388
389/*
390 * Do glDrawPixels of index pixels.
391 */
392static void draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
393 const struct gl_image *image )
394{
395 GLint width, height, widthInBytes;
396 const GLint desty = y;
397 GLint i, j;
398 GLdepth zspan[MAX_WIDTH];
399 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
400
401 assert(image);
402 assert(image->Format == GL_COLOR_INDEX);
403
404 width = image->Width;
405 height = image->Height;
406 if (image->Type == GL_BITMAP)
407 widthInBytes = (width + 7) / 8;
408 else
409 widthInBytes = width;
410
411 /* Fragment depth values */
412 if (ctx->Depth.Test || ctx->Fog.Enabled) {
413 GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
414 for (i=0;i<width;i++) {
415 zspan[i] = zval;
416 }
417 }
418
419 /* process the image row by row */
420 for (i=0;i<height;i++,y++) {
421 GLuint ispan[MAX_WIDTH];
422
423 /* convert to uints */
424 switch (image->Type) {
425 case GL_UNSIGNED_BYTE:
426 {
427 GLubyte *src = (GLubyte *) image->Data + i * width;
428 for (j=0;j<width;j++) {
429 ispan[j] = (GLuint) *src++;
430 }
431 }
432 break;
433 case GL_FLOAT:
434 {
435 GLfloat *src = (GLfloat *) image->Data + i * width;
436 for (j=0;j<width;j++) {
437 ispan[j] = (GLuint) (GLint) *src++;
438 }
439 }
440 break;
441 case GL_BITMAP:
442 {
443 GLubyte *src = (GLubyte *) image->Data + i * widthInBytes;
444 for (j=0;j<width;j++) {
445 ispan[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1;
446 }
447 }
448 break;
449 default:
450 gl_problem( ctx, "draw_index_pixels type" );
451 return;
452 }
453
454 /* apply shift and offset */
455 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
456 gl_shift_and_offset_ci( ctx, width, ispan );
457 }
458
459 if (ctx->Visual->RGBAflag) {
460 /* Convert index to RGBA and write to frame buffer */
461 GLubyte rgba[MAX_WIDTH][4];
462 gl_map_ci_to_rgba( ctx, width, ispan, rgba );
463 if (zoom) {
464 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
465 (const GLubyte (*)[4])rgba, desty );
466 }
467 else {
468 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
469 }
470 }
471 else {
472 /* optionally apply index map then write to frame buffer */
473 if (ctx->Pixel.MapColorFlag) {
474 gl_map_ci(ctx, width, ispan);
475 }
476 if (zoom) {
477 gl_write_zoomed_index_span( ctx, width, x, y, zspan, ispan, desty );
478 }
479 else {
480 gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
481 }
482 }
483 }
484
485}
486
487
488
489/*
490 * Do glDrawPixels of stencil image. The image datatype may either
491 * be GLubyte or GLbitmap.
492 */
493static void draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
494 const struct gl_image *image )
495{
496 GLint widthInBytes, width, height;
497 const GLint desty = y;
498 GLint i;
499 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
500
501 if (image->Type != GL_BYTE &&
502 image->Type != GL_UNSIGNED_BYTE &&
503 image->Type != GL_SHORT &&
504 image->Type != GL_UNSIGNED_SHORT &&
505 image->Type != GL_INT &&
506 image->Type != GL_UNSIGNED_INT &&
507 image->Type != GL_FLOAT &&
508 image->Type != GL_BITMAP) {
509 gl_error( ctx, GL_INVALID_OPERATION, "glDrawPixels(stencil type)");
510 return;
511 }
512
513 assert(image);
514 assert(image->Format == GL_STENCIL_INDEX);
515 assert(image->Type == GL_UNSIGNED_BYTE || image->Type == GL_BITMAP);
516
517 if (image->Type == GL_UNSIGNED_BYTE)
518 widthInBytes = image->Width;
519 else
520 widthInBytes = (image->Width + 7) / 8;
521 width = image->Width;
522 height = image->Height;
523
524 /* process the image row by row */
525 for (i=0;i<height;i++,y++) {
526 GLstencil *src = (GLstencil*)image->Data + i * widthInBytes;
527 GLstencil *stencilValues;
528 GLstencil stencilCopy[MAX_WIDTH];
529
530 if (image->Type == GL_BITMAP) {
531 /* convert bitmap data to GLubyte (0 or 1) data */
532 GLint j;
533 for (j = 0; j < width; j++) {
534 stencilCopy[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1;
535 }
536 src = stencilCopy;
537 }
538
539 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift
540 || ctx->Pixel.MapStencilFlag) {
541
542 /* make copy of stencil values */
543 if (src != stencilCopy)
544 MEMCPY( stencilCopy, src, width * sizeof(GLstencil));
545
546 /* apply shift and offset */
547 if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
548 gl_shift_and_offset_stencil( ctx, width, stencilCopy );
549 }
550
551 /* mapping */
552 if (ctx->Pixel.MapStencilFlag) {
553 gl_map_stencil( ctx, width, stencilCopy );
554 }
555
556 stencilValues = stencilCopy;
557 }
558 else {
559 /* use stencil values in-place */
560 stencilValues = src;
561 }
562
563 /* write stencil values to stencil buffer */
564 if (zoom) {
565 gl_write_zoomed_stencil_span( ctx, (GLuint) width, x, y,
566 stencilValues, desty );
567 }
568 else {
569 gl_write_stencil_span( ctx, (GLuint) width, x, y, stencilValues );
570 }
571 }
572}
573
574
575
576/*
577 * Do a glDrawPixels of depth values.
578 */
579static void draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
580 const struct gl_image *image )
581{
582 GLint width, height;
583 const GLint desty = y;
584 GLubyte rgba[MAX_WIDTH][4];
585 GLuint ispan[MAX_WIDTH];
586 const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
587 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
588
589 assert(image);
590 assert(image->Format == GL_DEPTH_COMPONENT);
591
592 width = image->Width;
593 height = image->Height;
594
595 /* Color or index */
596 if (ctx->Visual->RGBAflag) {
597 GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F);
598 GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F);
599 GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F);
600 GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F);
601 GLint i;
602 for (i=0; i<width; i++) {
603 rgba[i][RCOMP] = r;
604 rgba[i][GCOMP] = g;
605 rgba[i][BCOMP] = b;
606 rgba[i][ACOMP] = a;
607 }
608 }
609 else {
610 GLint i;
611 for (i=0;i<width;i++) {
612 ispan[i] = ctx->Current.RasterIndex;
613 }
614 }
615
616 if (image->Type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
617 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
618 /* Special case: directly write 16-bit depth values */
619 GLint j;
620 for (j=0;j<height;j++,y++) {
621 GLdepth *zptr = (GLdepth *) image->Data + j * width;
622 gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
623 }
624 }
625 else if (image->Type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint)
626 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
627 /* Special case: directly write 32-bit depth values */
628 GLint i, j;
629 /* Compute shift value to scale 32-bit uints down to depth values. */
630 GLuint shift = 0;
631 GLuint max = MAX_DEPTH;
632 while ((max&0x80000000)==0) {
633 max = max << 1;
634 shift++;
635 }
636 for (j=0;j<height;j++,y++) {
637 GLdepth zspan[MAX_WIDTH];
638 GLuint *zptr = (GLuint *) image->Data + j * width;
639 for (i=0;i<width;i++) {
640 zspan[i] = zptr[i] >> shift;
641 }
642 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
643 }
644 }
645 else {
646 /* General case (slower) */
647 GLint i, j;
648
649 /* process image row by row */
650 for (i=0;i<height;i++,y++) {
651 GLfloat depth[MAX_WIDTH];
652 GLdepth zspan[MAX_WIDTH];
653
654 switch (image->Type) {
655 case GL_UNSIGNED_SHORT:
656 {
657 GLushort *src = (GLushort *) image->Data + i * width;
658 for (j=0;j<width;j++) {
659 depth[j] = USHORT_TO_FLOAT( *src++ );
660 }
661 }
662 break;
663 case GL_UNSIGNED_INT:
664 {
665 GLuint *src = (GLuint *) image->Data + i * width;
666 for (j=0;j<width;j++) {
667 depth[j] = UINT_TO_FLOAT( *src++ );
668 }
669 }
670 break;
671 case GL_FLOAT:
672 {
673 GLfloat *src = (GLfloat *) image->Data + i * width;
674 for (j=0;j<width;j++) {
675 depth[j] = *src++;
676 }
677 }
678 break;
679 default:
680 gl_problem(ctx, "Bad type in draw_depth_pixels");
681 return;
682 }
683
684 /* apply depth scale and bias */
685 if (ctx->Pixel.DepthScale!=1.0 || ctx->Pixel.DepthBias!=0.0) {
686 for (j=0;j<width;j++) {
687 depth[j] = depth[j] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
688 }
689 }
690
691 /* clamp depth values to [0,1] and convert from floats to integers */
692 for (j=0;j<width;j++) {
693 zspan[j] = (GLdepth) (CLAMP( depth[j], 0.0F, 1.0F ) * DEPTH_SCALE);
694 }
695
696 if (ctx->Visual->RGBAflag) {
697 if (zoom) {
698 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
699 (const GLubyte (*)[4])rgba, desty );
700 }
701 else {
702 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
703 }
704 }
705 else {
706 if (zoom) {
707 gl_write_zoomed_index_span( ctx, width, x, y, zspan,
708 ispan, GL_BITMAP );
709 }
710 else {
711 gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
712 }
713 }
714
715 }
716 }
717}
718
719
720
721/* Simple unpacking parameters: */
722static struct gl_pixelstore_attrib NoUnpack = {
723 1, /* Alignment */
724 0, /* RowLength */
725 0, /* SkipPixels */
726 0, /* SkipRows */
727 0, /* ImageHeight */
728 0, /* SkipImages */
729 GL_FALSE, /* SwapBytes */
730 GL_FALSE /* LsbFirst */
731};
732
733
734/*
735 * Do glDrawPixels of RGBA pixels.
736 */
737static void draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
738 const struct gl_image *image )
739{
740 GLint width, height;
741 GLint i, j;
742 const GLint desty = y;
743 GLdepth zspan[MAX_WIDTH];
744 GLboolean quickDraw;
745 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
746
747 assert(image);
748
749 /* Try an optimized glDrawPixels first */
750 if (gl_direct_DrawPixels(ctx, &NoUnpack, image->Width, image->Height,
751 image->Format, image->Type, image->Data ))
752 return;
753
754 width = image->Width;
755 height = image->Height;
756
757 /* Fragment depth values */
758 if (ctx->Depth.Test || ctx->Fog.Enabled) {
759 /* fill in array of z values */
760 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
761 for (i=0;i<width;i++) {
762 zspan[i] = z;
763 }
764 }
765
766 if (ctx->RasterMask==0 && !zoom && x>=0 && y>=0
767 && x+width<=ctx->Buffer->Width && y+height<=ctx->Buffer->Height) {
768 quickDraw = GL_TRUE;
769 }
770 else {
771 quickDraw = GL_FALSE;
772 }
773
774 {
775 /* General solution */
776 GLboolean r_flag, g_flag, b_flag, a_flag, l_flag;
777 GLuint components;
778 GLubyte rgba[MAX_WIDTH][4];
779 GLfloat rf[MAX_WIDTH];
780 GLfloat gf[MAX_WIDTH];
781 GLfloat bf[MAX_WIDTH];
782 DEFARRAY(GLfloat,af,MAX_WIDTH);
783 CHECKARRAY(af,return);
784
785 r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE;
786 switch (image->Format) {
787 case GL_RED:
788 r_flag = GL_TRUE;
789 components = 1;
790 break;
791 case GL_GREEN:
792 g_flag = GL_TRUE;
793 components = 1;
794 break;
795 case GL_BLUE:
796 b_flag = GL_TRUE;
797 components = 1;
798 break;
799 case GL_ALPHA:
800 a_flag = GL_TRUE;
801 components = 1;
802 break;
803 case GL_RGB:
804 r_flag = g_flag = b_flag = GL_TRUE;
805 components = 3;
806 break;
807 case GL_LUMINANCE:
808 l_flag = GL_TRUE;
809 components = 1;
810 break;
811 case GL_LUMINANCE_ALPHA:
812 l_flag = a_flag = GL_TRUE;
813 components = 2;
814 break;
815 case GL_RGBA:
816 r_flag = g_flag = b_flag = a_flag = GL_TRUE;
817 components = 4;
818 break;
819 default:
820 gl_problem(ctx, "Bad type in draw_rgba_pixels");
821 goto cleanup;
822 }
823
824 /* process the image row by row */
825 for (i=0;i<height;i++,y++) {
826 /* convert to floats */
827 switch (image->Type) {
828 case GL_UNSIGNED_BYTE:
829 {
830 GLubyte *src = (GLubyte *) image->Data + i * width * components;
831 for (j=0;j<width;j++) {
832 if (l_flag) {
833 rf[j] = gf[j] = bf[j] = UBYTE_TO_FLOAT(*src++);
834 }
835 else {
836 rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
837 gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
838 bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
839 }
840 af[j] = a_flag ? UBYTE_TO_FLOAT(*src++) : 1.0;
841 }
842 }
843 break;
844 case GL_FLOAT:
845 {
846 GLfloat *src = (GLfloat *) image->Data + i * width * components;
847 for (j=0;j<width;j++) {
848 if (l_flag) {
849 rf[j] = gf[j] = bf[j] = *src++;
850 }
851 else {
852 rf[j] = r_flag ? *src++ : 0.0;
853 gf[j] = g_flag ? *src++ : 0.0;
854 bf[j] = b_flag ? *src++ : 0.0;
855 }
856 af[j] = a_flag ? *src++ : 1.0;
857 }
858 }
859 break;
860 default:
861 gl_problem( ctx, "draw_rgba_pixels type" );
862 goto cleanup;
863 }
864
865 /* apply scale and bias */
866 if (ctx->Pixel.ScaleOrBiasRGBA) {
867 gl_scale_and_bias_color(ctx, width, rf, gf, bf, af);
868 }
869
870 /* apply pixel mappings */
871 if (ctx->Pixel.MapColorFlag) {
872 gl_map_color(ctx, width, rf, gf, bf, af);
873 }
874
875 /* convert to integers */
876 for (j=0;j<width;j++) {
877 rgba[j][RCOMP] = (GLint) (rf[j] * 255.0F);
878 rgba[j][GCOMP] = (GLint) (gf[j] * 255.0F);
879 rgba[j][BCOMP] = (GLint) (bf[j] * 255.0F);
880 rgba[j][ACOMP] = (GLint) (af[j] * 255.0F);
881 }
882
883 /* write to frame buffer */
884 if (quickDraw) {
885 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y,
886 (const GLubyte (*)[4])rgba, NULL);
887 }
888 else if (zoom) {
889 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
890 (const GLubyte (*)[4])rgba, desty );
891 }
892 else {
893 gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP);
894 }
895 }
896cleanup:
897 UNDEFARRAY(af);
898 }
899}
900
901
902
903/*
904 * Execute glDrawPixels
905 */
906void gl_DrawPixels( GLcontext* ctx, struct gl_image *image )
907{
908 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels");
909
910
911 if (gl_image_error_test( ctx, image, "glDrawPixels" ))
912 return;
913
914 if (ctx->RenderMode==GL_RENDER) {
915 GLint x, y;
916 if (!ctx->Current.RasterPosValid) {
917 return;
918 }
919
920 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
921 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
922
923 switch (image->Format) {
924 case GL_COLOR_INDEX:
925 draw_index_pixels( ctx, x, y, image );
926 break;
927 case GL_STENCIL_INDEX:
928 draw_stencil_pixels( ctx, x, y, image );
929 break;
930 case GL_DEPTH_COMPONENT:
931 draw_depth_pixels( ctx, x, y, image );
932 break;
933 case GL_RED:
934 case GL_GREEN:
935 case GL_BLUE:
936 case GL_ALPHA:
937 case GL_RGB:
938 case GL_LUMINANCE:
939 case GL_LUMINANCE_ALPHA:
940 case GL_RGBA:
941 draw_rgba_pixels( ctx, x, y, image );
942 break;
943 default:
944 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels" );
945 return;
946 }
947 }
948 else if (ctx->RenderMode==GL_FEEDBACK) {
949 if (ctx->Current.RasterPosValid) {
950 GLfloat color[4];
951 GLfloat texcoord[4], invq;
952 UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor);
953 invq = 1.0F / ctx->Current.Texcoord[0][3];
954 texcoord[0] = ctx->Current.Texcoord[0][0] * invq;
955 texcoord[1] = ctx->Current.Texcoord[0][1] * invq;
956 texcoord[2] = ctx->Current.Texcoord[0][2] * invq;
957 texcoord[3] = ctx->Current.Texcoord[0][3];
958 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
959 gl_feedback_vertex( ctx,
960 ctx->Current.RasterPos,
961 color, ctx->Current.Index, texcoord );
962 }
963 }
964 else if (ctx->RenderMode==GL_SELECT) {
965 if (ctx->Current.RasterPosValid) {
966 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
967 }
968 }
969}
970
Note: See TracBrowser for help on using the repository browser.