• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 
26 #include "main/glheader.h"
27 #include "main/bufferobj.h"
28 #include "main/colormac.h"
29 #include "main/condrender.h"
30 #include "main/context.h"
31 #include "main/format_pack.h"
32 #include "main/format_utils.h"
33 #include "main/glformats.h"
34 #include "main/image.h"
35 
36 #include "main/macros.h"
37 #include "main/pack.h"
38 #include "main/pbo.h"
39 #include "main/pixeltransfer.h"
40 #include "main/state.h"
41 
42 #include "s_context.h"
43 #include "s_span.h"
44 #include "s_stencil.h"
45 #include "s_zoom.h"
46 
47 
48 /**
49  * Handle a common case of drawing GL_RGB/GL_UNSIGNED_BYTE into a
50  * MESA_FORMAT_XRGB888 or MESA_FORMAT_ARGB888 renderbuffer.
51  */
52 static void
fast_draw_rgb_ubyte_pixels(struct gl_context * ctx,struct gl_renderbuffer * rb,GLint x,GLint y,GLsizei width,GLsizei height,const struct gl_pixelstore_attrib * unpack,const GLvoid * pixels,bool flip_y)53 fast_draw_rgb_ubyte_pixels(struct gl_context *ctx,
54                            struct gl_renderbuffer *rb,
55                            GLint x, GLint y,
56                            GLsizei width, GLsizei height,
57                            const struct gl_pixelstore_attrib *unpack,
58                            const GLvoid *pixels,
59                            bool flip_y)
60 {
61    const GLubyte *src = (const GLubyte *)
62       _mesa_image_address2d(unpack, pixels, width,
63                             height, GL_RGB, GL_UNSIGNED_BYTE, 0, 0);
64    const GLint srcRowStride = _mesa_image_row_stride(unpack, width,
65                                                      GL_RGB, GL_UNSIGNED_BYTE);
66    GLint i, j;
67    GLubyte *dst;
68    GLint dstRowStride;
69 
70    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
71                                GL_MAP_WRITE_BIT, &dst, &dstRowStride,
72                                flip_y);
73 
74    if (!dst) {
75       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
76       return;
77    }
78 
79    if (ctx->Pixel.ZoomY == -1.0f) {
80       dst = dst + (height - 1) * dstRowStride;
81       dstRowStride = -dstRowStride;
82    }
83 
84    for (i = 0; i < height; i++) {
85       GLuint *dst4 = (GLuint *) dst;
86       for (j = 0; j < width; j++) {
87          dst4[j] = PACK_COLOR_8888(0xff, src[j*3+0], src[j*3+1], src[j*3+2]);
88       }
89       dst += dstRowStride;
90       src += srcRowStride;
91    }
92 
93    ctx->Driver.UnmapRenderbuffer(ctx, rb);
94 }
95 
96 
97 /**
98  * Handle a common case of drawing GL_RGBA/GL_UNSIGNED_BYTE into a
99  * MESA_FORMAT_ARGB888 or MESA_FORMAT_xRGB888 renderbuffer.
100  */
101 static void
fast_draw_rgba_ubyte_pixels(struct gl_context * ctx,struct gl_renderbuffer * rb,GLint x,GLint y,GLsizei width,GLsizei height,const struct gl_pixelstore_attrib * unpack,const GLvoid * pixels,bool flip_y)102 fast_draw_rgba_ubyte_pixels(struct gl_context *ctx,
103                            struct gl_renderbuffer *rb,
104                            GLint x, GLint y,
105                            GLsizei width, GLsizei height,
106                            const struct gl_pixelstore_attrib *unpack,
107                            const GLvoid *pixels,
108                            bool flip_y)
109 {
110    const GLubyte *src = (const GLubyte *)
111       _mesa_image_address2d(unpack, pixels, width,
112                             height, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
113    const GLint srcRowStride =
114       _mesa_image_row_stride(unpack, width, GL_RGBA, GL_UNSIGNED_BYTE);
115    GLint i, j;
116    GLubyte *dst;
117    GLint dstRowStride;
118 
119    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
120                                GL_MAP_WRITE_BIT, &dst, &dstRowStride,
121                                flip_y);
122 
123    if (!dst) {
124       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
125       return;
126    }
127 
128    if (ctx->Pixel.ZoomY == -1.0f) {
129       dst = dst + (height - 1) * dstRowStride;
130       dstRowStride = -dstRowStride;
131    }
132 
133    for (i = 0; i < height; i++) {
134       GLuint *dst4 = (GLuint *) dst;
135       for (j = 0; j < width; j++) {
136          dst4[j] = PACK_COLOR_8888(src[j*4+3], src[j*4+0],
137                                    src[j*4+1], src[j*4+2]);
138       }
139       dst += dstRowStride;
140       src += srcRowStride;
141    }
142 
143    ctx->Driver.UnmapRenderbuffer(ctx, rb);
144 }
145 
146 
147 /**
148  * Handle a common case of drawing a format/type combination that
149  * exactly matches the renderbuffer format.
150  */
151 static void
fast_draw_generic_pixels(struct gl_context * ctx,struct gl_renderbuffer * rb,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,const struct gl_pixelstore_attrib * unpack,const GLvoid * pixels,bool flip_y)152 fast_draw_generic_pixels(struct gl_context *ctx,
153                          struct gl_renderbuffer *rb,
154                          GLint x, GLint y,
155                          GLsizei width, GLsizei height,
156                          GLenum format, GLenum type,
157                          const struct gl_pixelstore_attrib *unpack,
158                          const GLvoid *pixels,
159                          bool flip_y)
160 {
161    const GLubyte *src = (const GLubyte *)
162       _mesa_image_address2d(unpack, pixels, width,
163                             height, format, type, 0, 0);
164    const GLint srcRowStride =
165       _mesa_image_row_stride(unpack, width, format, type);
166    const GLint rowLength = width * _mesa_get_format_bytes(rb->Format);
167    GLint i;
168    GLubyte *dst;
169    GLint dstRowStride;
170 
171    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
172                                GL_MAP_WRITE_BIT, &dst, &dstRowStride,
173                                flip_y);
174 
175    if (!dst) {
176       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
177       return;
178    }
179 
180    if (ctx->Pixel.ZoomY == -1.0f) {
181       dst = dst + (height - 1) * dstRowStride;
182       dstRowStride = -dstRowStride;
183    }
184 
185    for (i = 0; i < height; i++) {
186       memcpy(dst, src, rowLength);
187       dst += dstRowStride;
188       src += srcRowStride;
189    }
190 
191    ctx->Driver.UnmapRenderbuffer(ctx, rb);
192 }
193 
194 
195 /**
196  * Try to do a fast and simple RGB(a) glDrawPixels.
197  * Return:  GL_TRUE if success, GL_FALSE if slow path must be used instead
198  */
199 static GLboolean
fast_draw_rgba_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,const struct gl_pixelstore_attrib * userUnpack,const GLvoid * pixels)200 fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y,
201                       GLsizei width, GLsizei height,
202                       GLenum format, GLenum type,
203                       const struct gl_pixelstore_attrib *userUnpack,
204                       const GLvoid *pixels)
205 {
206    struct gl_framebuffer *fb = ctx->DrawBuffer;
207    struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
208    SWcontext *swrast = SWRAST_CONTEXT(ctx);
209    struct gl_pixelstore_attrib unpack;
210 
211    if (!rb)
212       return GL_TRUE; /* no-op */
213 
214    if (ctx->DrawBuffer->_NumColorDrawBuffers > 1 ||
215        (swrast->_RasterMask & ~CLIP_BIT) ||
216        ctx->Texture._EnabledCoordUnits ||
217        userUnpack->SwapBytes ||
218        ctx->Pixel.ZoomX != 1.0f ||
219        fabsf(ctx->Pixel.ZoomY) != 1.0f ||
220        ctx->_ImageTransferState) {
221       /* can't handle any of those conditions */
222       return GL_FALSE;
223    }
224 
225    unpack = *userUnpack;
226 
227    /* clipping */
228    if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, &unpack)) {
229       /* image was completely clipped: no-op, all done */
230       return GL_TRUE;
231    }
232 
233    if (format == GL_RGB &&
234        type == GL_UNSIGNED_BYTE &&
235        (rb->Format == MESA_FORMAT_B8G8R8X8_UNORM ||
236         rb->Format == MESA_FORMAT_B8G8R8A8_UNORM)) {
237       fast_draw_rgb_ubyte_pixels(ctx, rb, x, y, width, height,
238                                  &unpack, pixels, fb->FlipY);
239       return GL_TRUE;
240    }
241 
242    if (format == GL_RGBA &&
243        type == GL_UNSIGNED_BYTE &&
244        (rb->Format == MESA_FORMAT_B8G8R8X8_UNORM ||
245         rb->Format == MESA_FORMAT_B8G8R8A8_UNORM)) {
246       fast_draw_rgba_ubyte_pixels(ctx, rb, x, y, width, height,
247                                   &unpack, pixels, fb->FlipY);
248       return GL_TRUE;
249    }
250 
251    if (_mesa_format_matches_format_and_type(rb->Format, format, type,
252                                             ctx->Unpack.SwapBytes, NULL)) {
253       fast_draw_generic_pixels(ctx, rb, x, y, width, height,
254                                format, type, &unpack, pixels,
255                                fb->FlipY);
256       return GL_TRUE;
257    }
258 
259    /* can't handle this pixel format and/or data type */
260    return GL_FALSE;
261 }
262 
263 
264 
265 /*
266  * Draw stencil image.
267  */
268 static void
draw_stencil_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,const struct gl_pixelstore_attrib * unpack,const GLvoid * pixels)269 draw_stencil_pixels( struct gl_context *ctx, GLint x, GLint y,
270                      GLsizei width, GLsizei height,
271                      GLenum type,
272                      const struct gl_pixelstore_attrib *unpack,
273                      const GLvoid *pixels )
274 {
275    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
276    const GLenum destType = GL_UNSIGNED_BYTE;
277    GLint row;
278    GLubyte *values;
279 
280    values = malloc(width * sizeof(GLubyte));
281    if (!values) {
282       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
283       return;
284    }
285 
286    for (row = 0; row < height; row++) {
287       const GLvoid *source = _mesa_image_address2d(unpack, pixels,
288                                                    width, height,
289                                                    GL_STENCIL_INDEX, type,
290                                                    row, 0);
291       _mesa_unpack_stencil_span(ctx, width, destType, values,
292                                 type, source, unpack,
293                                 ctx->_ImageTransferState);
294       if (zoom) {
295          _swrast_write_zoomed_stencil_span(ctx, x, y, width,
296                                            x, y, values);
297       }
298       else {
299          _swrast_write_stencil_span(ctx, width, x, y, values);
300       }
301 
302       y++;
303    }
304 
305    free(values);
306 }
307 
308 
309 /*
310  * Draw depth image.
311  */
312 static void
draw_depth_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,const struct gl_pixelstore_attrib * unpack,const GLvoid * pixels)313 draw_depth_pixels( struct gl_context *ctx, GLint x, GLint y,
314                    GLsizei width, GLsizei height,
315                    GLenum type,
316                    const struct gl_pixelstore_attrib *unpack,
317                    const GLvoid *pixels )
318 {
319    const GLboolean scaleOrBias
320       = ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f;
321    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0f || ctx->Pixel.ZoomY != 1.0f;
322    SWspan span;
323 
324    INIT_SPAN(span, GL_BITMAP);
325    span.arrayMask = SPAN_Z;
326    _swrast_span_default_attribs(ctx, &span);
327 
328    if (type == GL_UNSIGNED_SHORT
329        && ctx->DrawBuffer->Visual.depthBits == 16
330        && !scaleOrBias
331        && !zoom
332        && width <= SWRAST_MAX_WIDTH
333        && !unpack->SwapBytes) {
334       /* Special case: directly write 16-bit depth values */
335       GLint row;
336       for (row = 0; row < height; row++) {
337          const GLushort *zSrc = (const GLushort *)
338             _mesa_image_address2d(unpack, pixels, width, height,
339                                   GL_DEPTH_COMPONENT, type, row, 0);
340          GLint i;
341          for (i = 0; i < width; i++)
342             span.array->z[i] = zSrc[i];
343          span.x = x;
344          span.y = y + row;
345          span.end = width;
346          _swrast_write_rgba_span(ctx, &span);
347       }
348    }
349    else if (type == GL_UNSIGNED_INT
350             && !scaleOrBias
351             && !zoom
352             && width <= SWRAST_MAX_WIDTH
353             && !unpack->SwapBytes) {
354       /* Special case: shift 32-bit values down to Visual.depthBits */
355       const GLint shift = 32 - ctx->DrawBuffer->Visual.depthBits;
356       GLint row;
357       for (row = 0; row < height; row++) {
358          const GLuint *zSrc = (const GLuint *)
359             _mesa_image_address2d(unpack, pixels, width, height,
360                                   GL_DEPTH_COMPONENT, type, row, 0);
361          if (shift == 0) {
362             memcpy(span.array->z, zSrc, width * sizeof(GLuint));
363          }
364          else {
365             GLint col;
366             for (col = 0; col < width; col++)
367                span.array->z[col] = zSrc[col] >> shift;
368          }
369          span.x = x;
370          span.y = y + row;
371          span.end = width;
372          _swrast_write_rgba_span(ctx, &span);
373       }
374    }
375    else {
376       /* General case */
377       const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
378       GLint skipPixels = 0;
379 
380       /* in case width > SWRAST_MAX_WIDTH do the copy in chunks */
381       while (skipPixels < width) {
382          const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH);
383          GLint row;
384          assert(span.end <= SWRAST_MAX_WIDTH);
385          for (row = 0; row < height; row++) {
386             const GLvoid *zSrc = _mesa_image_address2d(unpack,
387                                                       pixels, width, height,
388                                                       GL_DEPTH_COMPONENT, type,
389                                                       row, skipPixels);
390 
391             /* Set these for each row since the _swrast_write_* function may
392              * change them while clipping.
393              */
394             span.x = x + skipPixels;
395             span.y = y + row;
396             span.end = spanWidth;
397 
398             _mesa_unpack_depth_span(ctx, spanWidth,
399                                     GL_UNSIGNED_INT, span.array->z, depthMax,
400                                     type, zSrc, unpack);
401             if (zoom) {
402                _swrast_write_zoomed_depth_span(ctx, x, y, &span);
403             }
404             else {
405                _swrast_write_rgba_span(ctx, &span);
406             }
407          }
408          skipPixels += spanWidth;
409       }
410    }
411 }
412 
413 
414 
415 /**
416  * Draw RGBA image.
417  */
418 static void
draw_rgba_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,const struct gl_pixelstore_attrib * unpack,const GLvoid * pixels)419 draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y,
420                   GLsizei width, GLsizei height,
421                   GLenum format, GLenum type,
422                   const struct gl_pixelstore_attrib *unpack,
423                   const GLvoid *pixels )
424 {
425    const GLint imgX = x, imgY = y;
426    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
427    GLbitfield transferOps = ctx->_ImageTransferState;
428    SWspan span;
429 
430    /* Try an optimized glDrawPixels first */
431    if (fast_draw_rgba_pixels(ctx, x, y, width, height, format, type,
432                              unpack, pixels)) {
433       return;
434    }
435 
436    swrast_render_start(ctx);
437 
438    INIT_SPAN(span, GL_BITMAP);
439    _swrast_span_default_attribs(ctx, &span);
440    span.arrayMask = SPAN_RGBA;
441    span.arrayAttribs = VARYING_BIT_COL0; /* we're fill in COL0 attrib values */
442 
443    if (ctx->DrawBuffer->_NumColorDrawBuffers > 0) {
444       GLenum datatype = _mesa_get_format_datatype(
445                  ctx->DrawBuffer->_ColorDrawBuffers[0]->Format);
446       if (datatype != GL_FLOAT &&
447           ctx->Color.ClampFragmentColor != GL_FALSE) {
448          /* need to clamp colors before applying fragment ops */
449          transferOps |= IMAGE_CLAMP_BIT;
450       }
451    }
452 
453    /*
454     * General solution
455     */
456    {
457       const GLbitfield interpMask = span.interpMask;
458       const GLbitfield arrayMask = span.arrayMask;
459       GLint skipPixels = 0;
460       /* use span array for temp color storage */
461       GLfloat *rgba = (GLfloat *) span.array->attribs[VARYING_SLOT_COL0];
462       void *tempImage = NULL;
463 
464       /* We have to deal with GL_COLOR_INDEX manually because
465        * _mesa_format_convert does not handle this format. So what we do here is
466        * convert it to RGBA ubyte first and then convert from that to dst as
467        * usual.
468        */
469       if (format == GL_COLOR_INDEX) {
470          /* This will handle byte swapping and transferops if needed */
471          tempImage =
472             _mesa_unpack_color_index_to_rgba_ubyte(ctx, 2,
473                                                    pixels, format, type,
474                                                    width, height, 1,
475                                                    unpack,
476                                                    transferOps);
477          if (!tempImage) {
478             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
479             return;
480          }
481 
482          transferOps = 0;
483          pixels = tempImage;
484          format = GL_RGBA;
485          type = GL_UNSIGNED_BYTE;
486       } else if (unpack->SwapBytes) {
487          /* We have to handle byte-swapping scenarios before calling
488           * _mesa_format_convert
489           */
490          GLint swapSize = _mesa_sizeof_packed_type(type);
491          if (swapSize == 2 || swapSize == 4) {
492             int imageStride = _mesa_image_image_stride(unpack, width, height, format, type);
493 
494             tempImage = malloc(imageStride);
495             if (!tempImage) {
496                _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
497                return;
498             }
499 
500             _mesa_swap_bytes_2d_image(format, type, unpack,
501                                       width, height, tempImage, pixels);
502 
503             pixels = tempImage;
504          }
505       }
506 
507       const GLint srcStride
508          = _mesa_image_row_stride(unpack, width, format, type);
509 
510       /* if the span is wider than SWRAST_MAX_WIDTH we have to do it in chunks */
511       while (skipPixels < width) {
512          const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH);
513          const GLubyte *source
514             = (const GLubyte *) _mesa_image_address2d(unpack, pixels,
515                                                       width, height, format,
516                                                       type, 0, skipPixels);
517          GLint row;
518 
519          /* get image row as float/RGBA */
520          uint32_t srcMesaFormat = _mesa_format_from_format_and_type(format, type);
521          for (row = 0; row < height; row++) {
522             int dstRowStride = 4 * width * sizeof(float);
523             _mesa_format_convert(rgba, RGBA32_FLOAT, dstRowStride,
524                                  (void*)source, srcMesaFormat, srcStride,
525                                  spanWidth, 1, NULL);
526             if (transferOps)
527                _mesa_apply_rgba_transfer_ops(ctx, transferOps, spanWidth, (GLfloat (*)[4])rgba);
528 	    /* Set these for each row since the _swrast_write_* functions
529 	     * may change them while clipping/rendering.
530 	     */
531 	    span.array->ChanType = GL_FLOAT;
532 	    span.x = x + skipPixels;
533 	    span.y = y + row;
534 	    span.end = spanWidth;
535 	    span.arrayMask = arrayMask;
536 	    span.interpMask = interpMask;
537 	    if (zoom) {
538 	       _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba);
539 	    }
540 	    else {
541 	       _swrast_write_rgba_span(ctx, &span);
542 	    }
543 
544             source += srcStride;
545          } /* for row */
546 
547          skipPixels += spanWidth;
548       } /* while skipPixels < width */
549 
550       /* XXX this is ugly/temporary, to undo above change */
551       span.array->ChanType = CHAN_TYPE;
552 
553       free(tempImage);
554    }
555 
556    swrast_render_finish(ctx);
557 }
558 
559 
560 /**
561  * Draw depth+stencil values into a MESA_FORAMT_Z24_S8 or MESA_FORMAT_Z24_UNORM_S8_UINT
562  * renderbuffer.  No masking, zooming, scaling, etc.
563  */
564 static void
fast_draw_depth_stencil(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,const struct gl_pixelstore_attrib * unpack,const GLvoid * pixels)565 fast_draw_depth_stencil(struct gl_context *ctx, GLint x, GLint y,
566                         GLsizei width, GLsizei height,
567                         const struct gl_pixelstore_attrib *unpack,
568                         const GLvoid *pixels)
569 {
570    const GLenum format = GL_DEPTH_STENCIL_EXT;
571    const GLenum type = GL_UNSIGNED_INT_24_8;
572    struct gl_renderbuffer *rb =
573       ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
574    struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
575    GLubyte *src, *dst;
576    GLint srcRowStride, dstRowStride;
577    GLint i;
578 
579    src = _mesa_image_address2d(unpack, pixels, width, height,
580                                format, type, 0, 0);
581    srcRowStride = _mesa_image_row_stride(unpack, width, format, type);
582 
583    dst = _swrast_pixel_address(rb, x, y);
584    dstRowStride = srb->RowStride;
585 
586    for (i = 0; i < height; i++) {
587       _mesa_pack_uint_24_8_depth_stencil_row(rb->Format, width,
588                                              (const GLuint *) src, dst);
589       dst += dstRowStride;
590       src += srcRowStride;
591    }
592 }
593 
594 
595 
596 /**
597  * This is a bit different from drawing GL_DEPTH_COMPONENT pixels.
598  * The only per-pixel operations that apply are depth scale/bias,
599  * stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK,
600  * and pixel zoom.
601  * Also, only the depth buffer and stencil buffers are touched, not the
602  * color buffer(s).
603  */
604 static void
draw_depth_stencil_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,const struct gl_pixelstore_attrib * unpack,const GLvoid * pixels)605 draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
606                           GLsizei width, GLsizei height, GLenum type,
607                           const struct gl_pixelstore_attrib *unpack,
608                           const GLvoid *pixels)
609 {
610    const GLint imgX = x, imgY = y;
611    const GLboolean scaleOrBias
612       = ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F;
613    const GLuint stencilMask = ctx->Stencil.WriteMask[0];
614    const GLenum stencilType = GL_UNSIGNED_BYTE;
615    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
616    struct gl_renderbuffer *depthRb, *stencilRb;
617    struct gl_pixelstore_attrib clippedUnpack = *unpack;
618 
619    if (!zoom) {
620       if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height,
621                                  &clippedUnpack)) {
622          /* totally clipped */
623          return;
624       }
625    }
626 
627    depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
628    stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
629    assert(depthRb);
630    assert(stencilRb);
631 
632    if (depthRb == stencilRb &&
633        (depthRb->Format == MESA_FORMAT_S8_UINT_Z24_UNORM ||
634         depthRb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) &&
635        type == GL_UNSIGNED_INT_24_8 &&
636        !scaleOrBias &&
637        !zoom &&
638        ctx->Depth.Mask &&
639        (stencilMask & 0xff) == 0xff) {
640       fast_draw_depth_stencil(ctx, x, y, width, height,
641                               &clippedUnpack, pixels);
642    }
643    else {
644       /* sub-optimal cases:
645        * Separate depth/stencil buffers, or pixel transfer ops required.
646        */
647       /* XXX need to handle very wide images (skippixels) */
648       GLuint *zValues;  /* 32-bit Z values */
649       GLint i;
650 
651       zValues = malloc(width * sizeof(GLuint));
652       if (!zValues) {
653          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
654          return;
655       }
656 
657       for (i = 0; i < height; i++) {
658          const GLuint *depthStencilSrc = (const GLuint *)
659             _mesa_image_address2d(&clippedUnpack, pixels, width, height,
660                                   GL_DEPTH_STENCIL_EXT, type, i, 0);
661 
662          if (ctx->Depth.Mask) {
663             _mesa_unpack_depth_span(ctx, width,
664                                     GL_UNSIGNED_INT, /* dest type */
665                                     zValues,         /* dest addr */
666                                     0xffffffff,      /* depth max */
667                                     type,            /* src type */
668                                     depthStencilSrc, /* src addr */
669                                     &clippedUnpack);
670             if (zoom) {
671                _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x,
672                                            y + i, zValues);
673             }
674             else {
675                GLubyte *dst = _swrast_pixel_address(depthRb, x, y + i);
676                _mesa_pack_uint_z_row(depthRb->Format, width, zValues, dst);
677             }
678          }
679 
680          if (stencilMask != 0x0) {
681             GLubyte *stencilValues = (GLubyte *) zValues; /* re-use buffer */
682             /* get stencil values, with shift/offset/mapping */
683             _mesa_unpack_stencil_span(ctx, width, stencilType, stencilValues,
684                                       type, depthStencilSrc, &clippedUnpack,
685                                       ctx->_ImageTransferState);
686             if (zoom)
687                _swrast_write_zoomed_stencil_span(ctx, imgX, imgY, width,
688                                                   x, y + i, stencilValues);
689             else
690                _swrast_write_stencil_span(ctx, width, x, y + i, stencilValues);
691          }
692       }
693 
694       free(zValues);
695    }
696 }
697 
698 
699 /**
700  * Execute software-based glDrawPixels.
701  * By time we get here, all error checking will have been done.
702  */
703 void
_swrast_DrawPixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,const struct gl_pixelstore_attrib * unpack,const GLvoid * pixels)704 _swrast_DrawPixels( struct gl_context *ctx,
705 		    GLint x, GLint y,
706 		    GLsizei width, GLsizei height,
707 		    GLenum format, GLenum type,
708 		    const struct gl_pixelstore_attrib *unpack,
709 		    const GLvoid *pixels )
710 {
711    SWcontext *swrast = SWRAST_CONTEXT(ctx);
712    GLboolean save_vp_override = ctx->VertexProgram._Overriden;
713 
714    if (!_mesa_check_conditional_render(ctx))
715       return; /* don't draw */
716 
717    /* We are creating fragments directly, without going through vertex
718     * programs.
719     *
720     * This override flag tells the fragment processing code that its input
721     * comes from a non-standard source, and it may therefore not rely on
722     * optimizations that assume e.g. constant color if there is no color
723     * vertex array.
724     */
725    _mesa_set_vp_override(ctx, GL_TRUE);
726 
727    if (ctx->NewState)
728       _mesa_update_state(ctx);
729 
730    if (swrast->NewState)
731       _swrast_validate_derived( ctx );
732 
733    pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
734    if (!pixels) {
735       _mesa_set_vp_override(ctx, save_vp_override);
736       return;
737    }
738 
739    /*
740     * By time we get here, all error checking should have been done.
741     */
742    switch (format) {
743    case GL_STENCIL_INDEX:
744       swrast_render_start(ctx);
745       draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels );
746       swrast_render_finish(ctx);
747       break;
748    case GL_DEPTH_COMPONENT:
749       swrast_render_start(ctx);
750       draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels );
751       swrast_render_finish(ctx);
752       break;
753    case GL_DEPTH_STENCIL_EXT:
754       swrast_render_start(ctx);
755       draw_depth_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels);
756       swrast_render_finish(ctx);
757       break;
758    default:
759       /* all other formats should be color formats */
760       draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels);
761    }
762 
763    _mesa_set_vp_override(ctx, save_vp_override);
764 
765    _mesa_unmap_pbo_source(ctx, unpack);
766 }
767