s/GLuint/GLushort/ in read_depth_stencil_image()
[mesa.git] / src / mesa / swrast / s_drawpix.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 #include "glheader.h"
27 #include "bufferobj.h"
28 #include "context.h"
29 #include "convolve.h"
30 #include "image.h"
31 #include "macros.h"
32 #include "imports.h"
33 #include "pixel.h"
34
35 #include "s_context.h"
36 #include "s_drawpix.h"
37 #include "s_span.h"
38 #include "s_stencil.h"
39 #include "s_zoom.h"
40
41
42 /*
43 * Try to do a fast and simple RGB(a) glDrawPixels.
44 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
45 */
46 static GLboolean
47 fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
48 GLsizei width, GLsizei height,
49 GLenum format, GLenum type,
50 const struct gl_pixelstore_attrib *unpack,
51 const GLvoid *pixels)
52 {
53 const GLint imgX = x, imgY = y;
54 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
55 SWcontext *swrast = SWRAST_CONTEXT(ctx);
56 struct sw_span span;
57
58 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
59
60 if (swrast->_RasterMask & MULTI_DRAW_BIT)
61 return GL_FALSE;
62
63 if (ctx->Depth.Test)
64 _swrast_span_default_z(ctx, &span);
65 if (swrast->_FogEnabled)
66 _swrast_span_default_fog(ctx, &span);
67 if (ctx->Texture._EnabledCoordUnits)
68 _swrast_span_default_texcoords(ctx, &span);
69
70 if ((SWRAST_CONTEXT(ctx)->_RasterMask & ~CLIP_BIT) == 0
71 && ctx->Texture._EnabledCoordUnits == 0
72 && unpack->Alignment == 1
73 && !unpack->SwapBytes
74 && !unpack->LsbFirst) {
75
76 /* XXX there's a lot of clipping code here that should be replaced
77 * by a call to _mesa_clip_drawpixels().
78 */
79 GLint destX = x;
80 GLint destY = y;
81 GLint drawWidth = width; /* actual width drawn */
82 GLint drawHeight = height; /* actual height drawn */
83 GLint skipPixels = unpack->SkipPixels;
84 GLint skipRows = unpack->SkipRows;
85 GLint rowLength;
86
87 if (unpack->RowLength > 0)
88 rowLength = unpack->RowLength;
89 else
90 rowLength = width;
91
92 /* If we're not using pixel zoom then do all clipping calculations
93 * now. Otherwise, we'll let the _swrast_write_zoomed_*_span() functions
94 * handle the clipping.
95 */
96 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
97 /* horizontal clipping */
98 if (destX < ctx->DrawBuffer->_Xmin) {
99 skipPixels += (ctx->DrawBuffer->_Xmin - destX);
100 drawWidth -= (ctx->DrawBuffer->_Xmin - destX);
101 destX = ctx->DrawBuffer->_Xmin;
102 }
103 if (destX + drawWidth > ctx->DrawBuffer->_Xmax)
104 drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax);
105 if (drawWidth <= 0)
106 return GL_TRUE;
107
108 /* vertical clipping */
109 if (destY < ctx->DrawBuffer->_Ymin) {
110 skipRows += (ctx->DrawBuffer->_Ymin - destY);
111 drawHeight -= (ctx->DrawBuffer->_Ymin - destY);
112 destY = ctx->DrawBuffer->_Ymin;
113 }
114 if (destY + drawHeight > ctx->DrawBuffer->_Ymax)
115 drawHeight -= (destY + drawHeight - ctx->DrawBuffer->_Ymax);
116 if (drawHeight <= 0)
117 return GL_TRUE;
118 }
119 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
120 /* upside-down image */
121 /* horizontal clipping */
122 if (destX < ctx->DrawBuffer->_Xmin) {
123 skipPixels += (ctx->DrawBuffer->_Xmin - destX);
124 drawWidth -= (ctx->DrawBuffer->_Xmin - destX);
125 destX = ctx->DrawBuffer->_Xmin;
126 }
127 if (destX + drawWidth > ctx->DrawBuffer->_Xmax)
128 drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax);
129 if (drawWidth <= 0)
130 return GL_TRUE;
131
132 /* vertical clipping */
133 if (destY > ctx->DrawBuffer->_Ymax) {
134 skipRows += (destY - ctx->DrawBuffer->_Ymax);
135 drawHeight -= (destY - ctx->DrawBuffer->_Ymax);
136 destY = ctx->DrawBuffer->_Ymax;
137 }
138 if (destY - drawHeight < ctx->DrawBuffer->_Ymin)
139 drawHeight -= (ctx->DrawBuffer->_Ymin - (destY - drawHeight));
140 if (drawHeight <= 0)
141 return GL_TRUE;
142 }
143 else {
144 if (drawWidth > MAX_WIDTH)
145 return GL_FALSE; /* fall back to general case path */
146 }
147
148
149 /*
150 * Ready to draw!
151 * The window region at (destX, destY) of size (drawWidth, drawHeight)
152 * will be written to.
153 * We'll take pixel data from buffer pointed to by "pixels" but we'll
154 * skip "skipRows" rows and skip "skipPixels" pixels/row.
155 */
156
157 if (format == GL_RGBA && type == CHAN_TYPE
158 && ctx->_ImageTransferState==0) {
159 if (ctx->Visual.rgbMode) {
160 GLchan *src = (GLchan *) pixels
161 + (skipRows * rowLength + skipPixels) * 4;
162 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
163 /* no zooming */
164 GLint row;
165 for (row=0; row<drawHeight; row++) {
166 rb->PutRow(ctx, rb, drawWidth, destX, destY, src, NULL);
167 src += rowLength * 4;
168 destY++;
169 }
170 }
171 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
172 /* upside-down */
173 GLint row;
174 for (row=0; row<drawHeight; row++) {
175 destY--;
176 rb->PutRow(ctx, rb, drawWidth, destX, destY, src, NULL);
177 src += rowLength * 4;
178 }
179 }
180 else {
181 /* with zooming */
182 GLint row;
183 for (row=0; row<drawHeight; row++) {
184 span.x = destX;
185 span.y = destY + row;
186 span.end = drawWidth;
187 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
188 (CONST GLchan (*)[4]) src);
189 src += rowLength * 4;
190 }
191 }
192 }
193 return GL_TRUE;
194 }
195 else if (format == GL_RGB && type == CHAN_TYPE
196 && ctx->_ImageTransferState == 0) {
197 if (ctx->Visual.rgbMode) {
198 GLchan *src = (GLchan *) pixels
199 + (skipRows * rowLength + skipPixels) * 3;
200 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
201 GLint row;
202 for (row=0; row<drawHeight; row++) {
203 rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL);
204 src += rowLength * 3;
205 destY++;
206 }
207 }
208 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
209 /* upside-down */
210 GLint row;
211 for (row=0; row<drawHeight; row++) {
212 destY--;
213 rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL);
214 src += rowLength * 3;
215 }
216 }
217 else {
218 /* with zooming */
219 GLint row;
220 for (row=0; row<drawHeight; row++) {
221 span.x = destX;
222 span.y = destY;
223 span.end = drawWidth;
224 _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span,
225 (CONST GLchan (*)[3]) src);
226 src += rowLength * 3;
227 destY++;
228 }
229 }
230 }
231 return GL_TRUE;
232 }
233 else if (format == GL_LUMINANCE && type == CHAN_TYPE
234 && ctx->_ImageTransferState==0) {
235 if (ctx->Visual.rgbMode) {
236 GLchan *src = (GLchan *) pixels
237 + (skipRows * rowLength + skipPixels);
238 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
239 /* no zooming */
240 GLint row;
241 ASSERT(drawWidth <= MAX_WIDTH);
242 for (row=0; row<drawHeight; row++) {
243 GLint i;
244 for (i=0;i<drawWidth;i++) {
245 span.array->rgb[i][0] = src[i];
246 span.array->rgb[i][1] = src[i];
247 span.array->rgb[i][2] = src[i];
248 }
249 rb->PutRowRGB(ctx, rb, drawWidth, destX, destY,
250 span.array->rgb, NULL);
251 src += rowLength;
252 destY++;
253 }
254 }
255 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
256 /* upside-down */
257 GLint row;
258 ASSERT(drawWidth <= MAX_WIDTH);
259 for (row=0; row<drawHeight; row++) {
260 GLint i;
261 for (i=0;i<drawWidth;i++) {
262 span.array->rgb[i][0] = src[i];
263 span.array->rgb[i][1] = src[i];
264 span.array->rgb[i][2] = src[i];
265 }
266 destY--;
267 rb->PutRow(ctx, rb, drawWidth, destX, destY,
268 span.array->rgb, NULL);
269 src += rowLength;
270 }
271 }
272 else {
273 /* with zooming */
274 GLint row;
275 ASSERT(drawWidth <= MAX_WIDTH);
276 for (row=0; row<drawHeight; row++) {
277 GLint i;
278 for (i=0;i<drawWidth;i++) {
279 span.array->rgb[i][0] = src[i];
280 span.array->rgb[i][1] = src[i];
281 span.array->rgb[i][2] = src[i];
282 }
283 span.x = destX;
284 span.y = destY;
285 span.end = drawWidth;
286 _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span,
287 (CONST GLchan (*)[3]) span.array->rgb);
288 src += rowLength;
289 destY++;
290 }
291 }
292 }
293 return GL_TRUE;
294 }
295 else if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE
296 && ctx->_ImageTransferState == 0) {
297 if (ctx->Visual.rgbMode) {
298 GLchan *src = (GLchan *) pixels
299 + (skipRows * rowLength + skipPixels)*2;
300 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
301 /* no zooming */
302 GLint row;
303 ASSERT(drawWidth <= MAX_WIDTH);
304 for (row=0; row<drawHeight; row++) {
305 GLint i;
306 GLchan *ptr = src;
307 for (i=0;i<drawWidth;i++) {
308 span.array->rgba[i][0] = *ptr;
309 span.array->rgba[i][1] = *ptr;
310 span.array->rgba[i][2] = *ptr++;
311 span.array->rgba[i][3] = *ptr++;
312 }
313 rb->PutRow(ctx, rb, drawWidth, destX, destY,
314 span.array->rgba, NULL);
315 src += rowLength*2;
316 destY++;
317 }
318 }
319 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
320 /* upside-down */
321 GLint row;
322 ASSERT(drawWidth <= MAX_WIDTH);
323 for (row=0; row<drawHeight; row++) {
324 GLint i;
325 GLchan *ptr = src;
326 for (i=0;i<drawWidth;i++) {
327 span.array->rgba[i][0] = *ptr;
328 span.array->rgba[i][1] = *ptr;
329 span.array->rgba[i][2] = *ptr++;
330 span.array->rgba[i][3] = *ptr++;
331 }
332 destY--;
333 rb->PutRow(ctx, rb, drawWidth, destX, destY,
334 span.array->rgba, NULL);
335 src += rowLength*2;
336 }
337 }
338 else {
339 /* with zooming */
340 GLint row;
341 ASSERT(drawWidth <= MAX_WIDTH);
342 for (row=0; row<drawHeight; row++) {
343 GLchan *ptr = src;
344 GLint i;
345 for (i=0;i<drawWidth;i++) {
346 span.array->rgba[i][0] = *ptr;
347 span.array->rgba[i][1] = *ptr;
348 span.array->rgba[i][2] = *ptr++;
349 span.array->rgba[i][3] = *ptr++;
350 }
351 span.x = destX;
352 span.y = destY;
353 span.end = drawWidth;
354 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
355 (CONST GLchan (*)[4]) span.array->rgba);
356 src += rowLength*2;
357 destY++;
358 }
359 }
360 }
361 return GL_TRUE;
362 }
363 else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
364 GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
365 if (ctx->Visual.rgbMode) {
366 /* convert CI data to RGBA */
367 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
368 /* no zooming */
369 GLint row;
370 for (row=0; row<drawHeight; row++) {
371 ASSERT(drawWidth <= MAX_WIDTH);
372 _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba);
373 rb->PutRow(ctx, rb, drawWidth, destX, destY,
374 span.array->rgba, NULL);
375 src += rowLength;
376 destY++;
377 }
378 return GL_TRUE;
379 }
380 else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
381 /* upside-down */
382 GLint row;
383 for (row=0; row<drawHeight; row++) {
384 ASSERT(drawWidth <= MAX_WIDTH);
385 _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba);
386 destY--;
387 rb->PutRow(ctx, rb, drawWidth, destX, destY,
388 span.array->rgba, NULL);
389 src += rowLength;
390 }
391 return GL_TRUE;
392 }
393 else {
394 /* with zooming */
395 GLint row;
396 for (row=0; row<drawHeight; row++) {
397 ASSERT(drawWidth <= MAX_WIDTH);
398 _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba);
399 span.x = destX;
400 span.y = destY;
401 span.end = drawWidth;
402 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
403 (CONST GLchan (*)[4]) span.array->rgba);
404 src += rowLength;
405 destY++;
406 }
407 return GL_TRUE;
408 }
409 }
410 else if (ctx->_ImageTransferState==0) {
411 /* write CI data to CI frame buffer */
412 GLint row;
413 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
414 /* no zooming */
415 for (row=0; row<drawHeight; row++) {
416 GLuint index32[MAX_WIDTH];
417 GLint col;
418 for (col = 0; col < drawWidth; col++)
419 index32[col] = src[col];
420 rb->PutRow(ctx, rb, drawWidth, destX, destY, index32, NULL);
421 src += rowLength;
422 destY++;
423 }
424 return GL_TRUE;
425 }
426 else {
427 /* with zooming */
428 return GL_FALSE;
429 }
430 }
431 }
432 else {
433 /* can't handle this pixel format and/or data type here */
434 return GL_FALSE;
435 }
436 }
437
438 /* can't do a simple draw, have to use slow path */
439 return GL_FALSE;
440 }
441
442
443
444 /*
445 * Draw color index image.
446 */
447 static void
448 draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
449 GLsizei width, GLsizei height,
450 GLenum type,
451 const struct gl_pixelstore_attrib *unpack,
452 const GLvoid *pixels )
453 {
454 SWcontext *swrast = SWRAST_CONTEXT(ctx);
455 const GLint imgX = x, imgY = y;
456 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
457 GLint row, skipPixels;
458 struct sw_span span;
459
460 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_INDEX);
461
462 if (ctx->Depth.Test)
463 _swrast_span_default_z(ctx, &span);
464 if (swrast->_FogEnabled)
465 _swrast_span_default_fog(ctx, &span);
466
467 /*
468 * General solution
469 */
470 skipPixels = 0;
471 while (skipPixels < width) {
472 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
473 ASSERT(spanWidth <= MAX_WIDTH);
474 for (row = 0; row < height; row++) {
475 const GLvoid *source = _mesa_image_address2d(unpack, pixels,
476 width, height,
477 GL_COLOR_INDEX, type,
478 row, skipPixels);
479 _mesa_unpack_index_span(ctx, spanWidth, GL_UNSIGNED_INT,
480 span.array->index, type, source, unpack,
481 ctx->_ImageTransferState);
482
483 /* These may get changed during writing/clipping */
484 span.x = x + skipPixels;
485 span.y = y + row;
486 span.end = spanWidth;
487
488 if (zoom)
489 _swrast_write_zoomed_index_span(ctx, imgX, imgY, &span);
490 else
491 _swrast_write_index_span(ctx, &span);
492 }
493 skipPixels += spanWidth;
494 }
495 }
496
497
498
499 /*
500 * Draw stencil image.
501 */
502 static void
503 draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
504 GLsizei width, GLsizei height,
505 GLenum type,
506 const struct gl_pixelstore_attrib *unpack,
507 const GLvoid *pixels )
508 {
509 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
510 GLint skipPixels;
511
512 /* if width > MAX_WIDTH, have to process image in chunks */
513 skipPixels = 0;
514 while (skipPixels < width) {
515 const GLint spanX = x + skipPixels;
516 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
517 GLint row;
518 for (row = 0; row < height; row++) {
519 const GLint spanY = y + row;
520 GLstencil values[MAX_WIDTH];
521 GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
522 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
523 const GLvoid *source = _mesa_image_address2d(unpack, pixels,
524 width, height,
525 GL_COLOR_INDEX, type,
526 row, skipPixels);
527 _mesa_unpack_index_span(ctx, spanWidth, destType, values,
528 type, source, unpack,
529 ctx->_ImageTransferState);
530 if (ctx->_ImageTransferState & IMAGE_SHIFT_OFFSET_BIT) {
531 _mesa_shift_and_offset_stencil(ctx, spanWidth, values);
532 }
533 if (ctx->Pixel.MapStencilFlag) {
534 _mesa_map_stencil(ctx, spanWidth, values);
535 }
536
537 if (zoom) {
538 _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth,
539 spanX, spanY, values);
540 }
541 else {
542 _swrast_write_stencil_span(ctx, spanWidth, spanX, spanY, values);
543 }
544 }
545 skipPixels += spanWidth;
546 }
547 }
548
549
550 /*
551 * Draw depth image.
552 */
553 static void
554 draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
555 GLsizei width, GLsizei height,
556 GLenum type,
557 const struct gl_pixelstore_attrib *unpack,
558 const GLvoid *pixels )
559 {
560 SWcontext *swrast = SWRAST_CONTEXT(ctx);
561 const GLboolean scaleOrBias
562 = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
563 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
564 struct sw_span span;
565
566 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_Z);
567
568 _swrast_span_default_color(ctx, &span);
569
570 if (swrast->_FogEnabled)
571 _swrast_span_default_fog(ctx, &span);
572 if (ctx->Texture._EnabledCoordUnits)
573 _swrast_span_default_texcoords(ctx, &span);
574
575 if (type == GL_UNSIGNED_SHORT
576 && ctx->DrawBuffer->Visual.depthBits == 16
577 && !scaleOrBias
578 && !zoom
579 && ctx->Visual.rgbMode
580 && width <= MAX_WIDTH) {
581 /* Special case: directly write 16-bit depth values */
582 GLint row;
583 for (row = 0; row < height; row++) {
584 const GLushort *zSrc = (const GLushort *)
585 _mesa_image_address2d(unpack, pixels, width, height,
586 GL_DEPTH_COMPONENT, type, row, 0);
587 GLint i;
588 for (i = 0; i < width; i++)
589 span.array->z[i] = zSrc[i];
590 span.x = x;
591 span.y = y + row;
592 span.end = width;
593 _swrast_write_rgba_span(ctx, &span);
594 }
595 }
596 else if (type == GL_UNSIGNED_INT
597 && !scaleOrBias
598 && !zoom
599 && ctx->Visual.rgbMode
600 && width <= MAX_WIDTH) {
601 /* Special case: shift 32-bit values down to Visual.depthBits */
602 const GLint shift = 32 - ctx->DrawBuffer->Visual.depthBits;
603 GLint row;
604 for (row = 0; row < height; row++) {
605 const GLuint *zSrc = (const GLuint *)
606 _mesa_image_address2d(unpack, pixels, width, height,
607 GL_DEPTH_COMPONENT, type, row, 0);
608 if (shift == 0) {
609 _mesa_memcpy(span.array->z, zSrc, width * sizeof(GLuint));
610 }
611 else {
612 GLint col;
613 for (col = 0; col < width; col++)
614 span.array->z[col] = zSrc[col] >> shift;
615 }
616 span.x = x;
617 span.y = y + row;
618 span.end = width;
619 _swrast_write_rgba_span(ctx, &span);
620 }
621 }
622 else {
623 /* General case */
624 const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
625 GLint skipPixels = 0;
626
627 /* in case width > MAX_WIDTH do the copy in chunks */
628 while (skipPixels < width) {
629 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
630 GLint row;
631 ASSERT(span.end <= MAX_WIDTH);
632 for (row = 0; row < height; row++) {
633 const GLvoid *zSrc = _mesa_image_address2d(unpack,
634 pixels, width, height,
635 GL_DEPTH_COMPONENT, type,
636 row, skipPixels);
637
638 /* Set these for each row since the _swrast_write_* function may
639 * change them while clipping.
640 */
641 span.x = x + skipPixels;
642 span.y = y + row;
643 span.end = spanWidth;
644
645 _mesa_unpack_depth_span(ctx, spanWidth,
646 GL_UNSIGNED_INT, span.array->z, depthMax,
647 type, zSrc, unpack);
648 if (zoom) {
649 _swrast_write_zoomed_depth_span(ctx, x, y, &span);
650 }
651 else if (ctx->Visual.rgbMode) {
652 _swrast_write_rgba_span(ctx, &span);
653 }
654 else {
655 _swrast_write_index_span(ctx, &span);
656 }
657 }
658 skipPixels += spanWidth;
659 }
660 }
661 }
662
663
664
665 /*
666 * Draw RGBA image.
667 */
668 static void
669 draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
670 GLsizei width, GLsizei height,
671 GLenum format, GLenum type,
672 const struct gl_pixelstore_attrib *unpack,
673 const GLvoid *pixels )
674 {
675 SWcontext *swrast = SWRAST_CONTEXT(ctx);
676 const GLint imgX = x, imgY = y;
677 struct gl_renderbuffer *rb = NULL; /* only used for quickDraw path */
678 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
679 GLboolean quickDraw;
680 GLfloat *convImage = NULL;
681 GLuint transferOps = ctx->_ImageTransferState;
682 struct sw_span span;
683
684 INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
685
686 /* Try an optimized glDrawPixels first */
687 if (fast_draw_pixels(ctx, x, y, width, height, format, type, unpack, pixels))
688 return;
689
690 if (ctx->Depth.Test)
691 _swrast_span_default_z(ctx, &span);
692 if (swrast->_FogEnabled)
693 _swrast_span_default_fog(ctx, &span);
694 if (ctx->Texture._EnabledCoordUnits)
695 _swrast_span_default_texcoords(ctx, &span);
696
697 if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 && !zoom && x >= 0 && y >= 0
698 && x + width <= (GLint) ctx->DrawBuffer->Width
699 && y + height <= (GLint) ctx->DrawBuffer->Height
700 && ctx->DrawBuffer->_NumColorDrawBuffers[0] == 1) {
701 quickDraw = GL_TRUE;
702 rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
703 }
704 else {
705 quickDraw = GL_FALSE;
706 rb = NULL;
707 }
708
709 if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
710 /* Convolution has to be handled specially. We'll create an
711 * intermediate image, applying all pixel transfer operations
712 * up to convolution. Then we'll convolve the image. Then
713 * we'll proceed with the rest of the transfer operations and
714 * rasterize the image.
715 */
716 GLint row;
717 GLfloat *dest, *tmpImage;
718
719 tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
720 if (!tmpImage) {
721 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
722 return;
723 }
724 convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
725 if (!convImage) {
726 _mesa_free(tmpImage);
727 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
728 return;
729 }
730
731 /* Unpack the image and apply transfer ops up to convolution */
732 dest = tmpImage;
733 for (row = 0; row < height; row++) {
734 const GLvoid *source = _mesa_image_address2d(unpack,
735 pixels, width, height, format, type, row, 0);
736 _mesa_unpack_color_span_float(ctx, width, GL_RGBA, (GLfloat *) dest,
737 format, type, source, unpack,
738 transferOps & IMAGE_PRE_CONVOLUTION_BITS);
739 dest += width * 4;
740 }
741
742 /* do convolution */
743 if (ctx->Pixel.Convolution2DEnabled) {
744 _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
745 }
746 else {
747 ASSERT(ctx->Pixel.Separable2DEnabled);
748 _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
749 }
750 _mesa_free(tmpImage);
751
752 /* continue transfer ops and draw the convolved image */
753 unpack = &ctx->DefaultPacking;
754 pixels = convImage;
755 format = GL_RGBA;
756 type = GL_FLOAT;
757 transferOps &= IMAGE_POST_CONVOLUTION_BITS;
758 }
759
760 /*
761 * General solution
762 */
763 {
764 const GLbitfield interpMask = span.interpMask;
765 const GLbitfield arrayMask = span.arrayMask;
766 GLint skipPixels = 0;
767
768 /* if the span is wider than MAX_WIDTH we have to do it in chunks */
769 while (skipPixels < width) {
770 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
771 GLint row;
772
773 ASSERT(span.end <= MAX_WIDTH);
774
775 for (row = 0; row < height; row++) {
776 const GLvoid *source = _mesa_image_address2d(unpack,
777 pixels, width, height, format, type, row, skipPixels);
778
779 /* Set these for each row since the _swrast_write_* function may
780 * change them while clipping.
781 */
782 span.x = x + skipPixels;
783 span.y = y + row;
784 span.end = spanWidth;
785 span.arrayMask = arrayMask;
786 span.interpMask = interpMask;
787
788 _mesa_unpack_color_span_chan(ctx, spanWidth, GL_RGBA,
789 (GLchan *) span.array->rgba,
790 format, type, source, unpack,
791 transferOps);
792
793 if ((ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) ||
794 (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink))
795 continue;
796
797 /* draw the span */
798 if (quickDraw) {
799 rb->PutRow(ctx, rb, span.end, span.x, span.y,
800 span.array->rgba, NULL);
801 }
802 else if (zoom) {
803 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
804 (CONST GLchan (*)[4]) span.array->rgba);
805 }
806 else {
807 _swrast_write_rgba_span(ctx, &span);
808 }
809 }
810
811 skipPixels += spanWidth;
812 }
813 }
814
815 if (convImage) {
816 _mesa_free(convImage);
817 }
818 }
819
820
821 /**
822 * This is a bit different from drawing GL_DEPTH_COMPONENT pixels.
823 * The only per-pixel operations that apply are depth scale/bias,
824 * stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK,
825 * and pixel zoom.
826 * Also, only the depth buffer and stencil buffers are touched, not the
827 * color buffer(s).
828 */
829 static void
830 draw_depth_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
831 GLsizei width, GLsizei height, GLenum type,
832 const struct gl_pixelstore_attrib *unpack,
833 const GLvoid *pixels)
834 {
835 const GLint imgX = x, imgY = y;
836 const GLboolean scaleOrBias =
837 ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
838 const GLfloat depthScale = ctx->DrawBuffer->_DepthMaxF;
839 const GLuint stencilMask = ctx->Stencil.WriteMask[0];
840 const GLuint stencilType = (STENCIL_BITS == 8) ?
841 GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
842 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
843 struct gl_renderbuffer *depthRb, *stencilRb;
844 struct gl_pixelstore_attrib clippedUnpack = *unpack;
845
846 if (!zoom) {
847 if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height,
848 &clippedUnpack)) {
849 /* totally clipped */
850 return;
851 }
852 }
853
854 depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
855 stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
856 ASSERT(depthRb);
857 ASSERT(stencilRb);
858
859 if (depthRb->_BaseFormat == GL_DEPTH_STENCIL_EXT &&
860 stencilRb->_BaseFormat == GL_DEPTH_STENCIL_EXT &&
861 depthRb == stencilRb &&
862 !scaleOrBias &&
863 !zoom &&
864 ctx->Depth.Mask &&
865 (stencilMask & 0xff) == 0xff) {
866 /* This is the ideal case.
867 * Drawing GL_DEPTH_STENCIL pixels into a combined depth/stencil buffer.
868 * Plus, no pixel transfer ops, zooming, or masking needed.
869 */
870 GLint i;
871 for (i = 0; i < height; i++) {
872 const GLuint *src = (const GLuint *)
873 _mesa_image_address2d(&clippedUnpack, pixels, width, height,
874 GL_DEPTH_STENCIL_EXT, type, i, 0);
875 depthRb->PutRow(ctx, depthRb, width, x, y + i, src, NULL);
876 }
877 }
878 else {
879 /* sub-optimal cases:
880 * Separate depth/stencil buffers, or pixel transfer ops required.
881 */
882 /* XXX need to handle very wide images (skippixels) */
883 GLint i;
884
885 depthRb = ctx->DrawBuffer->_DepthBuffer;
886 stencilRb = ctx->DrawBuffer->_StencilBuffer;
887
888 for (i = 0; i < height; i++) {
889 const GLuint *depthStencilSrc = (const GLuint *)
890 _mesa_image_address2d(&clippedUnpack, pixels, width, height,
891 GL_DEPTH_STENCIL_EXT, type, i, 0);
892
893 if (ctx->Depth.Mask) {
894 if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 24) {
895 /* fast path 24-bit zbuffer */
896 GLuint zValues[MAX_WIDTH];
897 GLint j;
898 ASSERT(depthRb->DataType == GL_UNSIGNED_INT);
899 for (j = 0; j < width; j++) {
900 zValues[j] = depthStencilSrc[j] >> 8;
901 }
902 if (zoom)
903 _swrast_write_zoomed_z_span(ctx, imgX, imgY, width,
904 x, y + i, zValues);
905 else
906 depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
907 }
908 else if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 16) {
909 /* fast path 16-bit zbuffer */
910 GLushort zValues[MAX_WIDTH];
911 GLint j;
912 ASSERT(depthRb->DataType == GL_UNSIGNED_SHORT);
913 for (j = 0; j < width; j++) {
914 zValues[j] = depthStencilSrc[j] >> 16;
915 }
916 if (zoom)
917 _swrast_write_zoomed_z_span(ctx, imgX, imgY, width,
918 x, y + i, zValues);
919 else
920 depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
921 }
922 else {
923 /* general case */
924 GLuint zValues[MAX_WIDTH]; /* 16 or 32-bit Z value storage */
925 _mesa_unpack_depth_span(ctx, width,
926 depthRb->DataType, zValues, depthScale,
927 type, depthStencilSrc, &clippedUnpack);
928 if (zoom) {
929 _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x,
930 y + i, zValues);
931 }
932 else {
933 depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
934 }
935 }
936 }
937
938 if (stencilMask != 0x0) {
939 GLstencil stencilValues[MAX_WIDTH];
940 /* get stencil values, with shift/offset/mapping */
941 _mesa_unpack_stencil_span(ctx, width, stencilType, stencilValues,
942 type, depthStencilSrc, &clippedUnpack,
943 ctx->_ImageTransferState);
944 if (zoom)
945 _swrast_write_zoomed_stencil_span(ctx, imgX, imgY, width,
946 x, y + i, stencilValues);
947 else
948 _swrast_write_stencil_span(ctx, width, x, y + i, stencilValues);
949 }
950 }
951 }
952 }
953
954
955
956 /**
957 * Execute software-based glDrawPixels.
958 * By time we get here, all error checking will have been done.
959 */
960 void
961 _swrast_DrawPixels( GLcontext *ctx,
962 GLint x, GLint y,
963 GLsizei width, GLsizei height,
964 GLenum format, GLenum type,
965 const struct gl_pixelstore_attrib *unpack,
966 const GLvoid *pixels )
967 {
968 SWcontext *swrast = SWRAST_CONTEXT(ctx);
969
970 if (swrast->NewState)
971 _swrast_validate_derived( ctx );
972
973 if (unpack->BufferObj->Name) {
974 /* unpack from PBO */
975 GLubyte *buf;
976 if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
977 format, type, pixels)) {
978 _mesa_error(ctx, GL_INVALID_OPERATION,
979 "glDrawPixels(invalid PBO access)");
980 return;
981 }
982 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
983 GL_READ_ONLY_ARB,
984 unpack->BufferObj);
985 if (!buf) {
986 /* buffer is already mapped - that's an error */
987 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(PBO is mapped)");
988 return;
989 }
990 pixels = ADD_POINTERS(buf, pixels);
991 }
992
993 RENDER_START(swrast,ctx);
994
995 switch (format) {
996 case GL_STENCIL_INDEX:
997 draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels );
998 break;
999 case GL_DEPTH_COMPONENT:
1000 draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels );
1001 break;
1002 case GL_COLOR_INDEX:
1003 if (ctx->Visual.rgbMode)
1004 draw_rgba_pixels(ctx, x,y, width, height, format, type, unpack, pixels);
1005 else
1006 draw_index_pixels(ctx, x, y, width, height, type, unpack, pixels);
1007 break;
1008 case GL_RED:
1009 case GL_GREEN:
1010 case GL_BLUE:
1011 case GL_ALPHA:
1012 case GL_LUMINANCE:
1013 case GL_LUMINANCE_ALPHA:
1014 case GL_RGB:
1015 case GL_BGR:
1016 case GL_RGBA:
1017 case GL_BGRA:
1018 case GL_ABGR_EXT:
1019 draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels);
1020 break;
1021 case GL_DEPTH_STENCIL_EXT:
1022 draw_depth_stencil_pixels(ctx, x, y, width, height,
1023 type, unpack, pixels);
1024 break;
1025 default:
1026 _mesa_problem(ctx, "unexpected format in _swrast_DrawPixels");
1027 /* don't return yet, clean-up */
1028 }
1029
1030 RENDER_FINISH(swrast,ctx);
1031
1032 if (unpack->BufferObj->Name) {
1033 /* done with PBO so unmap it now */
1034 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
1035 unpack->BufferObj);
1036 }
1037 }
1038
1039
1040
1041 #if 0 /* experimental */
1042 /*
1043 * Execute glDrawDepthPixelsMESA().
1044 */
1045 void
1046 _swrast_DrawDepthPixelsMESA( GLcontext *ctx,
1047 GLint x, GLint y,
1048 GLsizei width, GLsizei height,
1049 GLenum colorFormat, GLenum colorType,
1050 const GLvoid *colors,
1051 GLenum depthType, const GLvoid *depths,
1052 const struct gl_pixelstore_attrib *unpack )
1053 {
1054 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1055
1056 if (swrast->NewState)
1057 _swrast_validate_derived( ctx );
1058
1059 RENDER_START(swrast,ctx);
1060
1061 switch (colorFormat) {
1062 case GL_COLOR_INDEX:
1063 if (ctx->Visual.rgbMode)
1064 draw_rgba_pixels(ctx, x,y, width, height, colorFormat, colorType,
1065 unpack, colors);
1066 else
1067 draw_index_pixels(ctx, x, y, width, height, colorType,
1068 unpack, colors);
1069 break;
1070 case GL_RED:
1071 case GL_GREEN:
1072 case GL_BLUE:
1073 case GL_ALPHA:
1074 case GL_LUMINANCE:
1075 case GL_LUMINANCE_ALPHA:
1076 case GL_RGB:
1077 case GL_BGR:
1078 case GL_RGBA:
1079 case GL_BGRA:
1080 case GL_ABGR_EXT:
1081 draw_rgba_pixels(ctx, x, y, width, height, colorFormat, colorType,
1082 unpack, colors);
1083 break;
1084 default:
1085 _mesa_problem(ctx, "unexpected format in glDrawDepthPixelsMESA");
1086 }
1087
1088 RENDER_FINISH(swrast,ctx);
1089 }
1090 #endif