fixed bad clear value
[mesa.git] / src / mesa / swrast / s_drawpix.c
1 /* $Id: s_drawpix.c,v 1.40 2002/11/25 20:26:59 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 5.0
6 *
7 * Copyright (C) 1999-2002 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 #include "glheader.h"
29 #include "colormac.h"
30 #include "context.h"
31 #include "convolve.h"
32 #include "image.h"
33 #include "macros.h"
34 #include "imports.h"
35 #include "mmath.h"
36 #include "pixel.h"
37
38 #include "s_context.h"
39 #include "s_drawpix.h"
40 #include "s_pixeltex.h"
41 #include "s_span.h"
42 #include "s_stencil.h"
43 #include "s_texture.h"
44 #include "s_zoom.h"
45
46
47
48 /*
49 * Given the dest position, size and skipPixels and skipRows values
50 * for a glDrawPixels command, perform clipping of the image bounds
51 * so the result lies withing the context's buffer bounds.
52 * Return: GL_TRUE if image is ready for drawing
53 * GL_FALSE if image was completely clipped away (draw nothing)
54 */
55 GLboolean
56 _mesa_clip_pixelrect(const GLcontext *ctx,
57 GLint *destX, GLint *destY,
58 GLsizei *width, GLsizei *height,
59 GLint *skipPixels, GLint *skipRows)
60 {
61 const GLframebuffer *buffer = ctx->DrawBuffer;
62
63 /* left clipping */
64 if (*destX < buffer->_Xmin) {
65 *skipPixels += (buffer->_Xmin - *destX);
66 *width -= (buffer->_Xmin - *destX);
67 *destX = buffer->_Xmin;
68 }
69 /* right clipping */
70 if (*destX + *width > buffer->_Xmax)
71 *width -= (*destX + *width - buffer->_Xmax);
72
73 if (*width <= 0)
74 return GL_FALSE;
75
76 /* bottom clipping */
77 if (*destY < buffer->_Ymin) {
78 *skipRows += (buffer->_Ymin - *destY);
79 *height -= (buffer->_Ymin - *destY);
80 *destY = buffer->_Ymin;
81 }
82 /* top clipping */
83 if (*destY + *height > buffer->_Ymax)
84 *height -= (*destY + *height - buffer->_Ymax);
85
86 if (*height <= 0)
87 return GL_TRUE;
88
89 return GL_TRUE;
90 }
91
92
93
94 /*
95 * Try to do a fast and simple RGB(a) glDrawPixels.
96 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
97 */
98 static GLboolean
99 fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
100 GLsizei width, GLsizei height,
101 GLenum format, GLenum type, const GLvoid *pixels)
102 {
103 SWcontext *swrast = SWRAST_CONTEXT(ctx);
104 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
105 struct sw_span span;
106
107 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
108
109 if (!ctx->Current.RasterPosValid) {
110 return GL_TRUE; /* no-op */
111 }
112
113 if (ctx->Depth.Test)
114 _mesa_span_default_z(ctx, &span);
115 if (ctx->Fog.Enabled)
116 _mesa_span_default_fog(ctx, &span);
117 if (ctx->Texture._EnabledUnits)
118 _mesa_span_default_texcoords(ctx, &span);
119
120 if ((SWRAST_CONTEXT(ctx)->_RasterMask & ~CLIP_BIT) == 0
121 && ctx->Texture._EnabledUnits == 0
122 && unpack->Alignment == 1
123 && !unpack->SwapBytes
124 && !unpack->LsbFirst) {
125
126 GLint destX = x;
127 GLint destY = y;
128 GLint drawWidth = width; /* actual width drawn */
129 GLint drawHeight = height; /* actual height drawn */
130 GLint skipPixels = unpack->SkipPixels;
131 GLint skipRows = unpack->SkipRows;
132 GLint rowLength;
133 GLdepth zSpan[MAX_WIDTH]; /* only used when zooming */
134 GLint zoomY0 = 0;
135
136 if (unpack->RowLength > 0)
137 rowLength = unpack->RowLength;
138 else
139 rowLength = width;
140
141 /* If we're not using pixel zoom then do all clipping calculations
142 * now. Otherwise, we'll let the _mesa_write_zoomed_*_span() functions
143 * handle the clipping.
144 */
145 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
146 /* horizontal clipping */
147 if (destX < ctx->DrawBuffer->_Xmin) {
148 skipPixels += (ctx->DrawBuffer->_Xmin - destX);
149 drawWidth -= (ctx->DrawBuffer->_Xmin - destX);
150 destX = ctx->DrawBuffer->_Xmin;
151 }
152 if (destX + drawWidth > ctx->DrawBuffer->_Xmax)
153 drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax);
154 if (drawWidth <= 0)
155 return GL_TRUE;
156
157 /* vertical clipping */
158 if (destY < ctx->DrawBuffer->_Ymin) {
159 skipRows += (ctx->DrawBuffer->_Ymin - destY);
160 drawHeight -= (ctx->DrawBuffer->_Ymin - destY);
161 destY = ctx->DrawBuffer->_Ymin;
162 }
163 if (destY + drawHeight > ctx->DrawBuffer->_Ymax)
164 drawHeight -= (destY + drawHeight - ctx->DrawBuffer->_Ymax);
165 if (drawHeight <= 0)
166 return GL_TRUE;
167 }
168 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
169 /* upside-down image */
170 /* horizontal clipping */
171 if (destX < ctx->DrawBuffer->_Xmin) {
172 skipPixels += (ctx->DrawBuffer->_Xmin - destX);
173 drawWidth -= (ctx->DrawBuffer->_Xmin - destX);
174 destX = ctx->DrawBuffer->_Xmin;
175 }
176 if (destX + drawWidth > ctx->DrawBuffer->_Xmax)
177 drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax);
178 if (drawWidth <= 0)
179 return GL_TRUE;
180
181 /* vertical clipping */
182 if (destY > ctx->DrawBuffer->_Ymax) {
183 skipRows += (destY - ctx->DrawBuffer->_Ymax);
184 drawHeight -= (destY - ctx->DrawBuffer->_Ymax);
185 destY = ctx->DrawBuffer->_Ymax;
186 }
187 if (destY - drawHeight < ctx->DrawBuffer->_Ymin)
188 drawHeight -= (ctx->DrawBuffer->_Ymin - (destY - drawHeight));
189 if (drawHeight <= 0)
190 return GL_TRUE;
191 }
192 else {
193 /* setup array of fragment Z value to pass to zoom function */
194 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->DepthMaxF);
195 GLint i;
196 ASSERT(drawWidth < MAX_WIDTH);
197 for (i=0; i<drawWidth; i++)
198 zSpan[i] = z;
199
200 /* save Y value of first row */
201 zoomY0 = IROUND(ctx->Current.RasterPos[1]);
202 }
203
204
205 /*
206 * Ready to draw!
207 * The window region at (destX, destY) of size (drawWidth, drawHeight)
208 * will be written to.
209 * We'll take pixel data from buffer pointed to by "pixels" but we'll
210 * skip "skipRows" rows and skip "skipPixels" pixels/row.
211 */
212
213 if (format == GL_RGBA && type == CHAN_TYPE
214 && ctx->_ImageTransferState==0) {
215 if (ctx->Visual.rgbMode) {
216 GLchan *src = (GLchan *) pixels
217 + (skipRows * rowLength + skipPixels) * 4;
218 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
219 /* no zooming */
220 GLint row;
221 for (row=0; row<drawHeight; row++) {
222 (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
223 (CONST GLchan (*)[4]) src, NULL);
224 src += rowLength * 4;
225 destY++;
226 }
227 }
228 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
229 /* upside-down */
230 GLint row;
231 for (row=0; row<drawHeight; row++) {
232 destY--;
233 (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
234 (CONST GLchan (*)[4]) src, NULL);
235 src += rowLength * 4;
236 }
237 }
238 else {
239 /* with zooming */
240 GLint row;
241 for (row=0; row<drawHeight; row++) {
242 span.x = destX;
243 span.y = destY;
244 span.end = drawWidth;
245 _mesa_write_zoomed_rgba_span(ctx, &span,
246 (CONST GLchan (*)[4]) src, zoomY0);
247 src += rowLength * 4;
248 destY++;
249 }
250 }
251 }
252 return GL_TRUE;
253 }
254 else if (format == GL_RGB && type == CHAN_TYPE
255 && ctx->_ImageTransferState == 0) {
256 if (ctx->Visual.rgbMode) {
257 GLchan *src = (GLchan *) pixels
258 + (skipRows * rowLength + skipPixels) * 3;
259 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
260 GLint row;
261 for (row=0; row<drawHeight; row++) {
262 (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
263 (CONST GLchan (*)[3]) src, NULL);
264 src += rowLength * 3;
265 destY++;
266 }
267 }
268 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
269 /* upside-down */
270 GLint row;
271 for (row=0; row<drawHeight; row++) {
272 destY--;
273 (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
274 (CONST GLchan (*)[3]) src, NULL);
275 src += rowLength * 3;
276 }
277 }
278 else {
279 /* with zooming */
280 GLint row;
281 for (row=0; row<drawHeight; row++) {
282 span.x = destX;
283 span.y = destY;
284 span.end = drawWidth;
285 _mesa_write_zoomed_rgb_span(ctx, &span,
286 (CONST GLchan (*)[3]) src, zoomY0);
287 src += rowLength * 3;
288 destY++;
289 }
290 }
291 }
292 return GL_TRUE;
293 }
294 else if (format == GL_LUMINANCE && type == CHAN_TYPE
295 && ctx->_ImageTransferState==0) {
296 if (ctx->Visual.rgbMode) {
297 GLchan *src = (GLchan *) pixels
298 + (skipRows * rowLength + skipPixels);
299 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
300 /* no zooming */
301 GLint row;
302 ASSERT(drawWidth < MAX_WIDTH);
303 for (row=0; row<drawHeight; row++) {
304 GLint i;
305 for (i=0;i<drawWidth;i++) {
306 span.array->rgb[i][0] = src[i];
307 span.array->rgb[i][1] = src[i];
308 span.array->rgb[i][2] = src[i];
309 }
310 (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
311 (CONST GLchan (*)[3]) span.array->rgb, NULL);
312 src += rowLength;
313 destY++;
314 }
315 }
316 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
317 /* upside-down */
318 GLint row;
319 ASSERT(drawWidth < MAX_WIDTH);
320 for (row=0; row<drawHeight; row++) {
321 GLint i;
322 for (i=0;i<drawWidth;i++) {
323 span.array->rgb[i][0] = src[i];
324 span.array->rgb[i][1] = src[i];
325 span.array->rgb[i][2] = src[i];
326 }
327 destY--;
328 (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
329 (CONST GLchan (*)[3]) span.array->rgb, NULL);
330 src += rowLength;
331 }
332 }
333 else {
334 /* with zooming */
335 GLint row;
336 ASSERT(drawWidth < MAX_WIDTH);
337 for (row=0; row<drawHeight; row++) {
338 GLint i;
339 for (i=0;i<drawWidth;i++) {
340 span.array->rgb[i][0] = src[i];
341 span.array->rgb[i][1] = src[i];
342 span.array->rgb[i][2] = src[i];
343 }
344 span.x = destX;
345 span.y = destY;
346 span.end = drawWidth;
347 _mesa_write_zoomed_rgb_span(ctx, &span,
348 (CONST GLchan (*)[3]) span.array->rgb, zoomY0);
349 src += rowLength;
350 destY++;
351 }
352 }
353 }
354 return GL_TRUE;
355 }
356 else if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE
357 && ctx->_ImageTransferState == 0) {
358 if (ctx->Visual.rgbMode) {
359 GLchan *src = (GLchan *) pixels
360 + (skipRows * rowLength + skipPixels)*2;
361 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
362 /* no zooming */
363 GLint row;
364 ASSERT(drawWidth < MAX_WIDTH);
365 for (row=0; row<drawHeight; row++) {
366 GLint i;
367 GLchan *ptr = src;
368 for (i=0;i<drawWidth;i++) {
369 span.array->rgba[i][0] = *ptr;
370 span.array->rgba[i][1] = *ptr;
371 span.array->rgba[i][2] = *ptr++;
372 span.array->rgba[i][3] = *ptr++;
373 }
374 (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
375 (CONST GLchan (*)[4]) span.array->rgba, NULL);
376 src += rowLength*2;
377 destY++;
378 }
379 }
380 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
381 /* upside-down */
382 GLint row;
383 ASSERT(drawWidth < MAX_WIDTH);
384 for (row=0; row<drawHeight; row++) {
385 GLint i;
386 GLchan *ptr = src;
387 for (i=0;i<drawWidth;i++) {
388 span.array->rgba[i][0] = *ptr;
389 span.array->rgba[i][1] = *ptr;
390 span.array->rgba[i][2] = *ptr++;
391 span.array->rgba[i][3] = *ptr++;
392 }
393 destY--;
394 (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
395 (CONST GLchan (*)[4]) span.array->rgba, NULL);
396 src += rowLength*2;
397 }
398 }
399 else {
400 /* with zooming */
401 GLint row;
402 ASSERT(drawWidth < MAX_WIDTH);
403 for (row=0; row<drawHeight; row++) {
404 GLchan *ptr = src;
405 GLint i;
406 for (i=0;i<drawWidth;i++) {
407 span.array->rgba[i][0] = *ptr;
408 span.array->rgba[i][1] = *ptr;
409 span.array->rgba[i][2] = *ptr++;
410 span.array->rgba[i][3] = *ptr++;
411 }
412 span.x = destX;
413 span.y = destY;
414 span.end = drawWidth;
415 _mesa_write_zoomed_rgba_span(ctx, &span,
416 (CONST GLchan (*)[4]) span.array->rgba, zoomY0);
417 src += rowLength*2;
418 destY++;
419 }
420 }
421 }
422 return GL_TRUE;
423 }
424 else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
425 GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
426 if (ctx->Visual.rgbMode) {
427 /* convert CI data to RGBA */
428 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
429 /* no zooming */
430 GLint row;
431 for (row=0; row<drawHeight; row++) {
432 ASSERT(drawWidth < MAX_WIDTH);
433 _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba);
434 (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
435 (const GLchan (*)[4]) span.array->rgba, NULL);
436 src += rowLength;
437 destY++;
438 }
439 return GL_TRUE;
440 }
441 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
442 /* upside-down */
443 GLint row;
444 for (row=0; row<drawHeight; row++) {
445 ASSERT(drawWidth < MAX_WIDTH);
446 _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba);
447 destY--;
448 (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
449 (CONST GLchan (*)[4]) span.array->rgba, NULL);
450 src += rowLength;
451 }
452 return GL_TRUE;
453 }
454 else {
455 /* with zooming */
456 GLint row;
457 for (row=0; row<drawHeight; row++) {
458 ASSERT(drawWidth < MAX_WIDTH);
459 _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba);
460 span.x = destX;
461 span.y = destY;
462 span.end = drawWidth;
463 _mesa_write_zoomed_rgba_span(ctx, &span,
464 (CONST GLchan (*)[4]) span.array->rgba, zoomY0);
465 src += rowLength;
466 destY++;
467 }
468 return GL_TRUE;
469 }
470 }
471 else if (ctx->_ImageTransferState==0) {
472 /* write CI data to CI frame buffer */
473 GLint row;
474 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
475 /* no zooming */
476 for (row=0; row<drawHeight; row++) {
477 (*swrast->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY,
478 src, NULL);
479 src += rowLength;
480 destY++;
481 }
482 return GL_TRUE;
483 }
484 else {
485 /* with zooming */
486 return GL_FALSE;
487 }
488 }
489 }
490 else {
491 /* can't handle this pixel format and/or data type here */
492 return GL_FALSE;
493 }
494 }
495
496 /* can't do a simple draw, have to use slow path */
497 return GL_FALSE;
498 }
499
500
501
502 /*
503 * Do glDrawPixels of index pixels.
504 */
505 static void
506 draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
507 GLsizei width, GLsizei height,
508 GLenum type, const GLvoid *pixels )
509 {
510 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
511 const GLint desty = y;
512 GLint row, drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
513 struct sw_span span;
514
515 INIT_SPAN(span, GL_BITMAP, drawWidth, 0, SPAN_INDEX);
516
517 if (ctx->Depth.Test)
518 _mesa_span_default_z(ctx, &span);
519 if (ctx->Fog.Enabled)
520 _mesa_span_default_fog(ctx, &span);
521
522 /*
523 * General solution
524 */
525 for (row = 0; row < height; row++, y++) {
526 const GLvoid *source = _mesa_image_address(&ctx->Unpack,
527 pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
528 _mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT,
529 span.array->index,
530 type, source, &ctx->Unpack,
531 ctx->_ImageTransferState);
532 span.x = x;
533 span.y = y;
534 span.end = drawWidth;
535 if (zoom)
536 _mesa_write_zoomed_index_span(ctx, &span, desty);
537 else
538 _mesa_write_index_span(ctx, &span);
539 }
540 }
541
542
543
544 /*
545 * Do glDrawPixels of stencil image. The image datatype may either
546 * be GLubyte or GLbitmap.
547 */
548 static void
549 draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
550 GLsizei width, GLsizei height,
551 GLenum type, const GLvoid *pixels )
552 {
553 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
554 const GLint desty = y;
555 GLint row, drawWidth;
556
557 if (type != GL_BYTE &&
558 type != GL_UNSIGNED_BYTE &&
559 type != GL_SHORT &&
560 type != GL_UNSIGNED_SHORT &&
561 type != GL_INT &&
562 type != GL_UNSIGNED_INT &&
563 type != GL_FLOAT &&
564 type != GL_BITMAP) {
565 _mesa_error( ctx, GL_INVALID_ENUM, "glDrawPixels(stencil type)");
566 return;
567 }
568
569 if (ctx->Visual.stencilBits == 0) {
570 _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawPixels(no stencil buffer)");
571 return;
572 }
573
574 drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
575
576 for (row = 0; row < height; row++, y++) {
577 GLstencil values[MAX_WIDTH];
578 GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
579 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
580 const GLvoid *source = _mesa_image_address(&ctx->Unpack,
581 pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
582 _mesa_unpack_index_span(ctx, drawWidth, destType, values,
583 type, source, &ctx->Unpack,
584 ctx->_ImageTransferState);
585 if (ctx->_ImageTransferState & IMAGE_SHIFT_OFFSET_BIT) {
586 _mesa_shift_and_offset_stencil( ctx, drawWidth, values );
587 }
588 if (ctx->Pixel.MapStencilFlag) {
589 _mesa_map_stencil( ctx, drawWidth, values );
590 }
591
592 if (zoom) {
593 _mesa_write_zoomed_stencil_span( ctx, (GLuint) drawWidth, x, y,
594 values, desty );
595 }
596 else {
597 _mesa_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values );
598 }
599 }
600 }
601
602
603 /*
604 * Do a glDrawPixels of depth values.
605 */
606 static void
607 draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
608 GLsizei width, GLsizei height,
609 GLenum type, const GLvoid *pixels )
610 {
611 const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
612 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
613 const GLint desty = y;
614 GLint drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
615 struct sw_span span;
616
617 INIT_SPAN(span, GL_BITMAP, drawWidth, 0, SPAN_Z);
618
619 if (type != GL_BYTE
620 && type != GL_UNSIGNED_BYTE
621 && type != GL_SHORT
622 && type != GL_UNSIGNED_SHORT
623 && type != GL_INT
624 && type != GL_UNSIGNED_INT
625 && type != GL_FLOAT) {
626 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawPixels(type)");
627 return;
628 }
629
630 _mesa_span_default_color(ctx, &span);
631
632 if (ctx->Fog.Enabled)
633 _mesa_span_default_fog(ctx, &span);
634 if (ctx->Texture._EnabledUnits)
635 _mesa_span_default_texcoords(ctx, &span);
636
637 if (type==GL_UNSIGNED_SHORT && ctx->Visual.depthBits == 16
638 && !bias_or_scale && !zoom && ctx->Visual.rgbMode) {
639 /* Special case: directly write 16-bit depth values */
640 GLint row;
641 span.x = x;
642 span.y = y;
643 span.end = drawWidth;
644 for (row = 0; row < height; row++, span.y++) {
645 const GLushort *zptr = (const GLushort *)
646 _mesa_image_address(&ctx->Unpack, pixels, width, height,
647 GL_DEPTH_COMPONENT, type, 0, row, 0);
648 GLint i;
649 for (i = 0; i < drawWidth; i++)
650 span.array->z[i] = zptr[i];
651 _mesa_write_rgba_span(ctx, &span);
652 }
653 }
654 else if (type==GL_UNSIGNED_INT && ctx->Visual.depthBits == 32
655 && !bias_or_scale && !zoom && ctx->Visual.rgbMode) {
656 /* Special case: directly write 32-bit depth values */
657 GLint row;
658 span.x = x;
659 span.y = y;
660 span.end = drawWidth;
661 for (row = 0; row < height; row++, span.y++) {
662 const GLuint *zptr = (const GLuint *)
663 _mesa_image_address(&ctx->Unpack, pixels, width, height,
664 GL_DEPTH_COMPONENT, type, 0, row, 0);
665 MEMCPY(span.array->z, zptr, drawWidth * sizeof(GLdepth));
666 _mesa_write_rgba_span(ctx, &span);
667 }
668 }
669 else {
670 /* General case */
671 GLint row;
672 span.x = x;
673 span.y = y;
674 span.end = drawWidth;
675 for (row = 0; row < height; row++, span.y++) {
676 GLfloat fspan[MAX_WIDTH];
677 const GLvoid *src = _mesa_image_address(&ctx->Unpack,
678 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
679 _mesa_unpack_depth_span( ctx, drawWidth, fspan, type, src,
680 &ctx->Unpack );
681 /* clamp depth values to [0,1] and convert from floats to integers */
682 {
683 const GLfloat zs = ctx->DepthMaxF;
684 GLint i;
685 for (i = 0; i < drawWidth; i++) {
686 span.array->z[i] = (GLdepth) (fspan[i] * zs + 0.5F);
687 }
688 }
689 if (ctx->Visual.rgbMode) {
690 if (zoom) {
691 _mesa_write_zoomed_rgba_span(ctx, &span,
692 (const GLchan (*)[4]) span.array->rgba, desty);
693 }
694 else
695 _mesa_write_rgba_span(ctx, &span);
696 }
697 else {
698 if (zoom)
699 _mesa_write_zoomed_index_span(ctx, &span, desty);
700 else
701 _mesa_write_index_span(ctx, &span);
702 }
703 }
704 }
705 }
706
707
708 /*
709 * Do glDrawPixels of RGBA pixels.
710 */
711 static void
712 draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
713 GLsizei width, GLsizei height,
714 GLenum format, GLenum type, const GLvoid *pixels )
715 {
716 SWcontext *swrast = SWRAST_CONTEXT(ctx);
717 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
718 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
719 const GLint desty = y;
720 GLboolean quickDraw;
721 GLfloat *convImage = NULL;
722 GLuint transferOps = ctx->_ImageTransferState;
723 struct sw_span span;
724
725 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
726
727 if (!_mesa_is_legal_format_and_type(format, type)) {
728 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawPixels(format or type)");
729 return;
730 }
731
732 /* Try an optimized glDrawPixels first */
733 if (fast_draw_pixels(ctx, x, y, width, height, format, type, pixels))
734 return;
735
736 if (ctx->Depth.Test)
737 _mesa_span_default_z(ctx, &span);
738 if (ctx->Fog.Enabled)
739 _mesa_span_default_fog(ctx, &span);
740 if (ctx->Texture._EnabledUnits)
741 _mesa_span_default_texcoords(ctx, &span);
742
743 if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 && !zoom && x >= 0 && y >= 0
744 && x + width <= (GLint) ctx->DrawBuffer->Width
745 && y + height <= (GLint) ctx->DrawBuffer->Height) {
746 quickDraw = GL_TRUE;
747 }
748 else {
749 quickDraw = GL_FALSE;
750 }
751
752 if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
753 /* Convolution has to be handled specially. We'll create an
754 * intermediate image, applying all pixel transfer operations
755 * up to convolution. Then we'll convolve the image. Then
756 * we'll proceed with the rest of the transfer operations and
757 * rasterize the image.
758 */
759 GLint row;
760 GLfloat *dest, *tmpImage;
761
762 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
763 if (!tmpImage) {
764 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
765 return;
766 }
767 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
768 if (!convImage) {
769 FREE(tmpImage);
770 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
771 return;
772 }
773
774 /* Unpack the image and apply transfer ops up to convolution */
775 dest = tmpImage;
776 for (row = 0; row < height; row++) {
777 const GLvoid *source = _mesa_image_address(unpack,
778 pixels, width, height, format, type, 0, row, 0);
779 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, (GLfloat *) dest,
780 format, type, source, unpack,
781 transferOps & IMAGE_PRE_CONVOLUTION_BITS,
782 GL_FALSE);
783 dest += width * 4;
784 }
785
786 /* do convolution */
787 if (ctx->Pixel.Convolution2DEnabled) {
788 _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
789 }
790 else {
791 ASSERT(ctx->Pixel.Separable2DEnabled);
792 _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
793 }
794 FREE(tmpImage);
795
796 /* continue transfer ops and draw the convolved image */
797 unpack = &_mesa_native_packing;
798 pixels = convImage;
799 format = GL_RGBA;
800 type = GL_FLOAT;
801 transferOps &= IMAGE_POST_CONVOLUTION_BITS;
802 }
803
804 /*
805 * General solution
806 */
807 {
808 GLint row;
809 if (width > MAX_WIDTH)
810 width = MAX_WIDTH;
811
812 for (row = 0; row < height; row++, y++) {
813 const GLvoid *source = _mesa_image_address(unpack,
814 pixels, width, height, format, type, 0, row, 0);
815
816 _mesa_unpack_chan_color_span(ctx, width, GL_RGBA,
817 (GLchan *) span.array->rgba,
818 format, type, source, unpack,
819 transferOps);
820
821 if ((ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) ||
822 (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink))
823 continue;
824
825 if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) {
826 span.end = width;
827 _swrast_pixel_texture(ctx, &span);
828 }
829
830 if (quickDraw) {
831 (*swrast->Driver.WriteRGBASpan)(ctx, width, x, y,
832 (CONST GLchan (*)[4]) span.array->rgba, NULL);
833 }
834 else if (zoom) {
835 span.x = x;
836 span.y = y;
837 span.end = width;
838 _mesa_write_zoomed_rgba_span(ctx, &span,
839 (CONST GLchan (*)[4]) span.array->rgba, desty);
840 }
841 else {
842 span.x = x;
843 span.y = y;
844 span.end = width;
845 _mesa_write_rgba_span(ctx, &span);
846 }
847 }
848 }
849
850 if (convImage) {
851 FREE(convImage);
852 }
853 }
854
855
856
857 /*
858 * Execute glDrawPixels
859 */
860 void
861 _swrast_DrawPixels( GLcontext *ctx,
862 GLint x, GLint y,
863 GLsizei width, GLsizei height,
864 GLenum format, GLenum type,
865 const struct gl_pixelstore_attrib *unpack,
866 const GLvoid *pixels )
867 {
868 SWcontext *swrast = SWRAST_CONTEXT(ctx);
869 (void) unpack;
870
871 if (swrast->NewState)
872 _swrast_validate_derived( ctx );
873
874 RENDER_START(swrast,ctx);
875
876 switch (format) {
877 case GL_STENCIL_INDEX:
878 draw_stencil_pixels( ctx, x, y, width, height, type, pixels );
879 break;
880 case GL_DEPTH_COMPONENT:
881 draw_depth_pixels( ctx, x, y, width, height, type, pixels );
882 break;
883 case GL_COLOR_INDEX:
884 if (ctx->Visual.rgbMode)
885 draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels);
886 else
887 draw_index_pixels(ctx, x, y, width, height, type, pixels);
888 break;
889 case GL_RED:
890 case GL_GREEN:
891 case GL_BLUE:
892 case GL_ALPHA:
893 case GL_LUMINANCE:
894 case GL_LUMINANCE_ALPHA:
895 case GL_RGB:
896 case GL_BGR:
897 case GL_RGBA:
898 case GL_BGRA:
899 case GL_ABGR_EXT:
900 draw_rgba_pixels(ctx, x, y, width, height, format, type, pixels);
901 break;
902 default:
903 _mesa_error( ctx, GL_INVALID_ENUM, "glDrawPixels(format)" );
904 }
905
906 RENDER_FINISH(swrast,ctx);
907 }
908
909
910
911 #if 0 /* experimental */
912 /*
913 * Execute glDrawDepthPixelsMESA().
914 */
915 void
916 _swrast_DrawDepthPixelsMESA( GLcontext *ctx,
917 GLint x, GLint y,
918 GLsizei width, GLsizei height,
919 GLenum colorFormat, GLenum colorType,
920 const GLvoid *colors,
921 GLenum depthType, const GLvoid *depths,
922 const struct gl_pixelstore_attrib *unpack )
923 {
924 SWcontext *swrast = SWRAST_CONTEXT(ctx);
925 (void) unpack;
926
927 if (swrast->NewState)
928 _swrast_validate_derived( ctx );
929
930 RENDER_START(swrast,ctx);
931
932 switch (colorFormat) {
933 case GL_COLOR_INDEX:
934 if (ctx->Visual.rgbMode)
935 draw_rgba_pixels(ctx, x,y, width, height, colorFormat, colorType, colors);
936 else
937 draw_index_pixels(ctx, x, y, width, height, colorType, colors);
938 break;
939 case GL_RED:
940 case GL_GREEN:
941 case GL_BLUE:
942 case GL_ALPHA:
943 case GL_LUMINANCE:
944 case GL_LUMINANCE_ALPHA:
945 case GL_RGB:
946 case GL_BGR:
947 case GL_RGBA:
948 case GL_BGRA:
949 case GL_ABGR_EXT:
950 draw_rgba_pixels(ctx, x, y, width, height, colorFormat, colorType, colors);
951 break;
952 default:
953 _mesa_error( ctx, GL_INVALID_ENUM,
954 "glDrawDepthPixelsMESA(colorFormat)" );
955 }
956
957 RENDER_FINISH(swrast,ctx);
958 }
959 #endif