2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
30 #include "histogram.h"
36 #include "s_context.h"
39 #include "s_stencil.h"
45 * Determine if there's overlap in an image copy.
46 * This test also compensates for the fact that copies are done from
47 * bottom to top and overlaps can sometimes be handled correctly
48 * without making a temporary image copy.
49 * \return GL_TRUE if the regions overlap, GL_FALSE otherwise.
52 regions_overlap(GLint srcx
, GLint srcy
,
53 GLint dstx
, GLint dsty
,
54 GLint width
, GLint height
,
55 GLfloat zoomX
, GLfloat zoomY
)
57 if (zoomX
== 1.0 && zoomY
== 1.0) {
59 if (srcx
>= dstx
+ width
|| (srcx
+ width
<= dstx
)) {
62 else if (srcy
< dsty
) { /* this is OK */
65 else if (srcy
> dsty
+ height
) {
73 /* add one pixel of slop when zooming, just to be safe */
74 if ((srcx
> dstx
+ (width
* zoomX
) + 1) || (srcx
+ width
+ 1 < dstx
)) {
77 else if ((srcy
< dsty
) && (srcy
+ height
< dsty
+ (height
* zoomY
))) {
80 else if ((srcy
> dsty
) && (srcy
+ height
> dsty
+ (height
* zoomY
))) {
91 * RGBA copypixels with convolution.
94 copy_conv_rgba_pixels(GLcontext
*ctx
, GLint srcx
, GLint srcy
,
95 GLint width
, GLint height
, GLint destx
, GLint desty
)
97 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
99 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
100 const GLbitfield transferOps
= ctx
->_ImageTransferState
;
101 const GLboolean sink
= (ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
)
102 || (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
);
103 GLfloat
*dest
, *tmpImage
, *convImage
;
106 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
109 _swrast_span_default_z(ctx
, &span
);
110 if (swrast
->_FogEnabled
)
111 _swrast_span_default_fog(ctx
, &span
);
114 /* allocate space for GLfloat image */
115 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
117 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels");
120 convImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
122 _mesa_free(tmpImage
);
123 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels");
127 /* read source image as float/RGBA */
129 for (row
= 0; row
< height
; row
++) {
130 _swrast_read_rgba_span(ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
131 width
, srcx
, srcy
+ row
, GL_FLOAT
, dest
);
135 /* do the image transfer ops which preceed convolution */
136 for (row
= 0; row
< height
; row
++) {
137 GLfloat (*rgba
)[4] = (GLfloat (*)[4]) (tmpImage
+ row
* width
* 4);
138 _mesa_apply_rgba_transfer_ops(ctx
,
139 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
,
144 if (ctx
->Pixel
.Convolution2DEnabled
) {
145 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
148 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
149 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
151 _mesa_free(tmpImage
);
153 /* do remaining post-convolution image transfer ops */
154 for (row
= 0; row
< height
; row
++) {
155 GLfloat (*rgba
)[4] = (GLfloat (*)[4]) (convImage
+ row
* width
* 4);
156 _mesa_apply_rgba_transfer_ops(ctx
,
157 transferOps
& IMAGE_POST_CONVOLUTION_BITS
,
162 /* write the new image */
163 for (row
= 0; row
< height
; row
++) {
164 const GLfloat
*src
= convImage
+ row
* width
* 4;
165 GLvoid
*rgba
= span
.array
->color
.sz1
.rgba
; /* row storage */
167 /* copy convolved colors into span array */
168 _mesa_memcpy(rgba
, src
, width
* 4 * sizeof(GLfloat
));
172 span
.y
= desty
+ row
;
174 span
.array
->ChanType
= GL_FLOAT
;
176 _swrast_write_zoomed_rgba_span(ctx
, destx
, desty
, &span
, rgba
);
179 _swrast_write_rgba_span(ctx
, &span
);
183 span
.array
->ChanType
= CHAN_TYPE
;
186 _mesa_free(convImage
);
194 copy_rgba_pixels(GLcontext
*ctx
, GLint srcx
, GLint srcy
,
195 GLint width
, GLint height
, GLint destx
, GLint desty
)
197 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
198 GLfloat
*tmpImage
, *p
;
199 GLint sy
, dy
, stepy
, row
;
200 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
202 const GLuint transferOps
= ctx
->_ImageTransferState
;
205 if (!ctx
->ReadBuffer
->_ColorReadBuffer
) {
206 /* no readbuffer - OK */
210 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
211 copy_conv_rgba_pixels(ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
215 /* Determine if copy should be done bottom-to-top or top-to-bottom */
217 /* top-down max-to-min */
218 sy
= srcy
+ height
- 1;
219 dy
= desty
+ height
- 1;
223 /* bottom-up min-to-max */
229 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
230 overlapping
= regions_overlap(srcx
, srcy
, destx
, desty
, width
, height
,
231 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
234 overlapping
= GL_FALSE
;
237 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
239 _swrast_span_default_z(ctx
, &span
);
240 if (swrast
->_FogEnabled
)
241 _swrast_span_default_fog(ctx
, &span
);
244 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* sizeof(GLfloat
) * 4);
246 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels" );
249 /* read the source image as RGBA/float */
251 for (row
= 0; row
< height
; row
++) {
252 _swrast_read_rgba_span( ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
253 width
, srcx
, sy
+ row
, GL_FLOAT
, p
);
259 tmpImage
= NULL
; /* silence compiler warnings */
263 ASSERT(width
< MAX_WIDTH
);
265 for (row
= 0; row
< height
; row
++, sy
+= stepy
, dy
+= stepy
) {
266 GLvoid
*rgba
= span
.array
->color
.sz4
.rgba
;
268 /* Get row/span of source pixels */
270 /* get from buffered image */
271 _mesa_memcpy(rgba
, p
, width
* sizeof(GLfloat
) * 4);
275 /* get from framebuffer */
276 _swrast_read_rgba_span( ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
277 width
, srcx
, sy
, GL_FLOAT
, rgba
);
281 _mesa_apply_rgba_transfer_ops(ctx
, transferOps
, width
,
282 (GLfloat (*)[4]) rgba
);
285 /* Write color span */
289 span
.array
->ChanType
= GL_FLOAT
;
291 _swrast_write_zoomed_rgba_span(ctx
, destx
, desty
, &span
, rgba
);
294 _swrast_write_rgba_span(ctx
, &span
);
298 span
.array
->ChanType
= CHAN_TYPE
; /* restore */
301 _mesa_free(tmpImage
);
306 copy_ci_pixels( GLcontext
*ctx
, GLint srcx
, GLint srcy
,
307 GLint width
, GLint height
,
308 GLint destx
, GLint desty
)
310 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
314 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
315 const GLboolean shift_or_offset
= ctx
->Pixel
.IndexShift
|| ctx
->Pixel
.IndexOffset
;
319 if (!ctx
->ReadBuffer
->_ColorReadBuffer
) {
320 /* no readbuffer - OK */
324 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_INDEX
);
326 /* Determine if copy should be bottom-to-top or top-to-bottom */
328 /* top-down max-to-min */
329 sy
= srcy
+ height
- 1;
330 dy
= desty
+ height
- 1;
334 /* bottom-up min-to-max */
340 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
341 overlapping
= regions_overlap(srcx
, srcy
, destx
, desty
, width
, height
,
342 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
345 overlapping
= GL_FALSE
;
349 _swrast_span_default_z(ctx
, &span
);
350 if (swrast
->_FogEnabled
)
351 _swrast_span_default_fog(ctx
, &span
);
355 tmpImage
= (GLuint
*) _mesa_malloc(width
* height
* sizeof(GLuint
));
357 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels" );
362 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
363 _swrast_read_index_span( ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
364 width
, srcx
, ssy
, p
);
370 tmpImage
= NULL
; /* silence compiler warning */
374 for (j
= 0; j
< height
; j
++, sy
+= stepy
, dy
+= stepy
) {
375 /* Get color indexes */
377 _mesa_memcpy(span
.array
->index
, p
, width
* sizeof(GLuint
));
381 _swrast_read_index_span( ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
382 width
, srcx
, sy
, span
.array
->index
);
385 /* Apply shift, offset, look-up table */
386 if (shift_or_offset
) {
387 _mesa_shift_and_offset_ci( ctx
, width
, span
.array
->index
);
389 if (ctx
->Pixel
.MapColorFlag
) {
390 _mesa_map_ci( ctx
, width
, span
.array
->index
);
393 /* write color indexes */
398 _swrast_write_zoomed_index_span(ctx
, destx
, desty
, &span
);
400 _swrast_write_index_span(ctx
, &span
);
404 _mesa_free(tmpImage
);
409 * Convert floating point Z values to integer Z values with pixel transfer's
413 scale_and_bias_z(GLcontext
*ctx
, GLuint width
,
414 const GLfloat depth
[], GLuint z
[])
416 const GLuint depthMax
= ctx
->DrawBuffer
->_DepthMax
;
419 if (depthMax
<= 0xffffff &&
420 ctx
->Pixel
.DepthScale
== 1.0 &&
421 ctx
->Pixel
.DepthBias
== 0.0) {
422 /* no scale or bias and no clamping and no worry of overflow */
423 const GLfloat depthMaxF
= ctx
->DrawBuffer
->_DepthMaxF
;
424 for (i
= 0; i
< width
; i
++) {
425 z
[i
] = (GLuint
) (depth
[i
] * depthMaxF
);
429 /* need to be careful with overflow */
430 const GLdouble depthMaxF
= ctx
->DrawBuffer
->_DepthMaxF
;
431 for (i
= 0; i
< width
; i
++) {
432 GLdouble d
= depth
[i
] * ctx
->Pixel
.DepthScale
+ ctx
->Pixel
.DepthBias
;
433 d
= CLAMP(d
, 0.0, 1.0) * depthMaxF
;
448 copy_depth_pixels( GLcontext
*ctx
, GLint srcx
, GLint srcy
,
449 GLint width
, GLint height
,
450 GLint destx
, GLint desty
)
452 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
453 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
454 struct gl_renderbuffer
*readRb
= fb
->_DepthBuffer
;
455 GLfloat
*p
, *tmpImage
;
458 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
463 /* no readbuffer - OK */
467 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_Z
);
469 /* Determine if copy should be bottom-to-top or top-to-bottom */
471 /* top-down max-to-min */
472 sy
= srcy
+ height
- 1;
473 dy
= desty
+ height
- 1;
477 /* bottom-up min-to-max */
483 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
484 overlapping
= regions_overlap(srcx
, srcy
, destx
, desty
, width
, height
,
485 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
488 overlapping
= GL_FALSE
;
491 _swrast_span_default_color(ctx
, &span
);
492 if (swrast
->_FogEnabled
)
493 _swrast_span_default_fog(ctx
, &span
);
497 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* sizeof(GLfloat
));
499 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels" );
503 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
504 _swrast_read_depth_span_float(ctx
, readRb
, width
, srcx
, ssy
, p
);
510 tmpImage
= NULL
; /* silence compiler warning */
514 for (j
= 0; j
< height
; j
++, sy
+= stepy
, dy
+= stepy
) {
515 GLfloat depth
[MAX_WIDTH
];
516 /* get depth values */
518 _mesa_memcpy(depth
, p
, width
* sizeof(GLfloat
));
522 _swrast_read_depth_span_float(ctx
, readRb
, width
, srcx
, sy
, depth
);
525 /* apply scale and bias */
526 scale_and_bias_z(ctx
, width
, depth
, span
.array
->z
);
528 /* write depth values */
532 if (fb
->Visual
.rgbMode
) {
534 _swrast_write_zoomed_rgba_span(ctx
, destx
, desty
, &span
,
537 _swrast_write_rgba_span(ctx
, &span
);
541 _swrast_write_zoomed_index_span(ctx
, destx
, desty
, &span
);
543 _swrast_write_index_span(ctx
, &span
);
548 _mesa_free(tmpImage
);
554 copy_stencil_pixels( GLcontext
*ctx
, GLint srcx
, GLint srcy
,
555 GLint width
, GLint height
,
556 GLint destx
, GLint desty
)
558 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
559 struct gl_renderbuffer
*rb
= fb
->_StencilBuffer
;
562 GLstencil
*p
, *tmpImage
;
563 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
564 const GLboolean shift_or_offset
= ctx
->Pixel
.IndexShift
|| ctx
->Pixel
.IndexOffset
;
568 /* no readbuffer - OK */
572 /* Determine if copy should be bottom-to-top or top-to-bottom */
574 /* top-down max-to-min */
575 sy
= srcy
+ height
- 1;
576 dy
= desty
+ height
- 1;
580 /* bottom-up min-to-max */
586 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
587 overlapping
= regions_overlap(srcx
, srcy
, destx
, desty
, width
, height
,
588 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
591 overlapping
= GL_FALSE
;
596 tmpImage
= (GLstencil
*) _mesa_malloc(width
* height
* sizeof(GLstencil
));
598 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels" );
602 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
603 _swrast_read_stencil_span( ctx
, rb
, width
, srcx
, ssy
, p
);
609 tmpImage
= NULL
; /* silence compiler warning */
613 for (j
= 0; j
< height
; j
++, sy
+= stepy
, dy
+= stepy
) {
614 GLstencil stencil
[MAX_WIDTH
];
616 /* Get stencil values */
618 _mesa_memcpy(stencil
, p
, width
* sizeof(GLstencil
));
622 _swrast_read_stencil_span( ctx
, rb
, width
, srcx
, sy
, stencil
);
625 /* Apply shift, offset, look-up table */
626 if (shift_or_offset
) {
627 _mesa_shift_and_offset_stencil( ctx
, width
, stencil
);
629 if (ctx
->Pixel
.MapStencilFlag
) {
630 _mesa_map_stencil( ctx
, width
, stencil
);
633 /* Write stencil values */
635 _swrast_write_zoomed_stencil_span(ctx
, destx
, desty
, width
,
639 _swrast_write_stencil_span( ctx
, width
, destx
, dy
, stencil
);
644 _mesa_free(tmpImage
);
649 * This isn't terribly efficient. If a driver really has combined
650 * depth/stencil buffers the driver should implement an optimized
651 * CopyPixels function.
654 copy_depth_stencil_pixels(GLcontext
*ctx
,
655 const GLint srcX
, const GLint srcY
,
656 const GLint width
, const GLint height
,
657 const GLint destX
, const GLint destY
)
659 struct gl_renderbuffer
*stencilReadRb
, *depthReadRb
, *depthDrawRb
;
662 GLstencil
*tempStencilImage
= NULL
, *stencilPtr
= NULL
;
663 GLfloat
*tempDepthImage
= NULL
, *depthPtr
= NULL
;
664 const GLfloat depthScale
= ctx
->DrawBuffer
->_DepthMaxF
;
665 const GLuint stencilMask
= ctx
->Stencil
.WriteMask
[0];
666 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
667 const GLboolean shiftOrOffset
668 = ctx
->Pixel
.IndexShift
|| ctx
->Pixel
.IndexOffset
;
669 const GLboolean scaleOrBias
670 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
673 depthDrawRb
= ctx
->DrawBuffer
->_DepthBuffer
;
674 depthReadRb
= ctx
->ReadBuffer
->_DepthBuffer
;
675 stencilReadRb
= ctx
->ReadBuffer
->_StencilBuffer
;
679 ASSERT(stencilReadRb
);
681 /* Determine if copy should be bottom-to-top or top-to-bottom */
683 /* top-down max-to-min */
684 sy
= srcY
+ height
- 1;
685 dy
= destY
+ height
- 1;
689 /* bottom-up min-to-max */
695 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
696 overlapping
= regions_overlap(srcX
, srcY
, destX
, destY
, width
, height
,
697 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
700 overlapping
= GL_FALSE
;
706 if (stencilMask
!= 0x0) {
708 = (GLstencil
*) _mesa_malloc(width
* height
* sizeof(GLstencil
));
709 if (!tempStencilImage
) {
710 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels");
714 /* get copy of stencil pixels */
715 stencilPtr
= tempStencilImage
;
716 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
717 _swrast_read_stencil_span(ctx
, stencilReadRb
,
718 width
, srcX
, ssy
, stencilPtr
);
721 stencilPtr
= tempStencilImage
;
724 if (ctx
->Depth
.Mask
) {
726 = (GLfloat
*) _mesa_malloc(width
* height
* sizeof(GLfloat
));
727 if (!tempDepthImage
) {
728 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels");
729 _mesa_free(tempStencilImage
);
733 /* get copy of depth pixels */
734 depthPtr
= tempDepthImage
;
735 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
736 _swrast_read_depth_span_float(ctx
, depthReadRb
,
737 width
, srcX
, ssy
, depthPtr
);
740 depthPtr
= tempDepthImage
;
744 for (j
= 0; j
< height
; j
++, sy
+= stepy
, dy
+= stepy
) {
745 if (stencilMask
!= 0x0) {
746 GLstencil stencil
[MAX_WIDTH
];
748 /* Get stencil values */
750 _mesa_memcpy(stencil
, stencilPtr
, width
* sizeof(GLstencil
));
754 _swrast_read_stencil_span(ctx
, stencilReadRb
,
755 width
, srcX
, sy
, stencil
);
758 /* Apply shift, offset, look-up table */
760 _mesa_shift_and_offset_stencil(ctx
, width
, stencil
);
762 if (ctx
->Pixel
.MapStencilFlag
) {
763 _mesa_map_stencil(ctx
, width
, stencil
);
768 _swrast_write_zoomed_stencil_span(ctx
, destX
, destY
, width
,
772 _swrast_write_stencil_span( ctx
, width
, destX
, dy
, stencil
);
776 if (ctx
->Depth
.Mask
) {
777 GLfloat depth
[MAX_WIDTH
];
778 GLuint zVals32
[MAX_WIDTH
];
779 GLushort zVals16
[MAX_WIDTH
];
783 /* get depth values */
785 _mesa_memcpy(depth
, depthPtr
, width
* sizeof(GLfloat
));
789 _swrast_read_depth_span_float(ctx
, depthReadRb
,
790 width
, srcX
, sy
, depth
);
795 _mesa_scale_and_bias_depth(ctx
, width
, depth
);
797 /* convert to integer Z values */
798 if (depthDrawRb
->DataType
== GL_UNSIGNED_SHORT
) {
800 for (k
= 0; k
< width
; k
++)
801 zVals16
[k
] = (GLushort
) (depth
[k
] * depthScale
);
807 for (k
= 0; k
< width
; k
++)
808 zVals32
[k
] = (GLuint
) (depth
[k
] * depthScale
);
815 _swrast_write_zoomed_z_span(ctx
, destX
, destY
, width
,
819 _swrast_put_row(ctx
, depthDrawRb
, width
, destX
, dy
, zVals
, zBytes
);
824 if (tempStencilImage
)
825 _mesa_free(tempStencilImage
);
828 _mesa_free(tempDepthImage
);
834 * Try to do a fast copy pixels.
837 fast_copy_pixels(GLcontext
*ctx
,
838 GLint srcX
, GLint srcY
, GLsizei width
, GLsizei height
,
839 GLint dstX
, GLint dstY
, GLenum type
)
841 struct gl_framebuffer
*srcFb
= ctx
->ReadBuffer
;
842 struct gl_framebuffer
*dstFb
= ctx
->DrawBuffer
;
843 struct gl_renderbuffer
*srcRb
, *dstRb
;
846 if (SWRAST_CONTEXT(ctx
)->_RasterMask
!= 0x0 ||
847 ctx
->Pixel
.ZoomX
!= 1.0F
||
848 ctx
->Pixel
.ZoomY
!= 1.0F
||
849 ctx
->_ImageTransferState
) {
850 /* can't handle these */
854 if (type
== GL_COLOR
) {
855 if (dstFb
->_NumColorDrawBuffers
[0] != 1)
857 srcRb
= srcFb
->_ColorReadBuffer
;
858 dstRb
= dstFb
->_ColorDrawBuffers
[0][0];
860 else if (type
== GL_STENCIL
) {
861 srcRb
= srcFb
->_StencilBuffer
;
862 dstRb
= dstFb
->_StencilBuffer
;
864 else if (type
== GL_DEPTH
) {
865 srcRb
= srcFb
->_DepthBuffer
;
866 dstRb
= dstFb
->_DepthBuffer
;
868 else if (type
== GL_DEPTH_STENCIL_EXT
) {
870 srcRb
= srcFb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
871 dstRb
= dstFb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
874 /* src and dst renderbuffers must be same format and type */
875 if (!srcRb
|| !dstRb
||
876 srcRb
->DataType
!= dstRb
->DataType
||
877 srcRb
->_BaseFormat
!= dstRb
->_BaseFormat
) {
881 /* clipping not supported */
882 if (srcX
< 0 || srcX
+ width
> srcFb
->Width
||
883 srcY
< 0 || srcY
+ height
> srcFb
->Width
||
884 dstX
< dstFb
->_Xmin
|| dstX
+ width
> dstFb
->_Xmax
||
885 dstY
< dstFb
->_Ymin
|| dstY
+ height
> dstFb
->_Ymax
) {
889 /* overlapping src/dst doesn't matter, just determine Y direction */
891 /* top-down max-to-min */
892 srcY
= srcY
+ height
- 1;
893 dstY
= dstY
+ height
- 1;
897 /* bottom-up min-to-max */
901 for (row
= 0; row
< height
; row
++) {
902 GLuint temp
[MAX_WIDTH
][4];
903 srcRb
->GetRow(ctx
, srcRb
, width
, srcX
, srcY
, temp
);
904 dstRb
->PutRow(ctx
, dstRb
, width
, dstX
, dstY
, temp
, NULL
);
914 * Do software-based glCopyPixels.
915 * By time we get here, all parameters will have been error-checked.
918 _swrast_CopyPixels( GLcontext
*ctx
,
919 GLint srcx
, GLint srcy
, GLsizei width
, GLsizei height
,
920 GLint destx
, GLint desty
, GLenum type
)
922 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
923 RENDER_START(swrast
,ctx
);
925 if (swrast
->NewState
)
926 _swrast_validate_derived( ctx
);
928 if (!fast_copy_pixels(ctx
, srcx
, srcy
, width
, height
, destx
, desty
, type
)) {
931 if (ctx
->Visual
.rgbMode
) {
932 copy_rgba_pixels( ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
935 copy_ci_pixels( ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
939 copy_depth_pixels( ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
942 copy_stencil_pixels( ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
944 case GL_DEPTH_STENCIL_EXT
:
945 copy_depth_stencil_pixels(ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
948 _mesa_problem(ctx
, "unexpected type in _swrast_CopyPixels");
952 RENDER_FINISH(swrast
,ctx
);