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