2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 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
)
98 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
99 const GLbitfield transferOps
= ctx
->_ImageTransferState
;
100 const GLboolean sink
= (ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
)
101 || (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
);
102 GLfloat
*dest
, *tmpImage
, *convImage
;
105 INIT_SPAN(span
, GL_BITMAP
);
106 _swrast_span_default_attribs(ctx
, &span
);
107 span
.arrayMask
= SPAN_RGBA
;
108 span
.arrayAttribs
= FRAG_BIT_COL0
;
110 /* allocate space for GLfloat image */
111 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
113 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels");
116 convImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
118 _mesa_free(tmpImage
);
119 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels");
123 /* read source image as float/RGBA */
125 for (row
= 0; row
< height
; row
++) {
126 _swrast_read_rgba_span(ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
127 width
, srcx
, srcy
+ row
, GL_FLOAT
, dest
);
131 /* do the image transfer ops which preceed convolution */
132 for (row
= 0; row
< height
; row
++) {
133 GLfloat (*rgba
)[4] = (GLfloat (*)[4]) (tmpImage
+ row
* width
* 4);
134 _mesa_apply_rgba_transfer_ops(ctx
,
135 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
,
140 if (ctx
->Pixel
.Convolution2DEnabled
) {
141 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
144 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
145 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
147 _mesa_free(tmpImage
);
149 /* do remaining post-convolution image transfer ops */
150 for (row
= 0; row
< height
; row
++) {
151 GLfloat (*rgba
)[4] = (GLfloat (*)[4]) (convImage
+ row
* width
* 4);
152 _mesa_apply_rgba_transfer_ops(ctx
,
153 transferOps
& IMAGE_POST_CONVOLUTION_BITS
,
158 /* write the new image */
159 for (row
= 0; row
< height
; row
++) {
160 const GLfloat
*src
= convImage
+ row
* width
* 4;
161 GLfloat
*rgba
= (GLfloat
*) span
.array
->attribs
[FRAG_ATTRIB_COL0
];
163 /* copy convolved colors into span array */
164 _mesa_memcpy(rgba
, src
, width
* 4 * sizeof(GLfloat
));
168 span
.y
= desty
+ row
;
170 span
.array
->ChanType
= GL_FLOAT
;
172 _swrast_write_zoomed_rgba_span(ctx
, destx
, desty
, &span
, rgba
);
175 _swrast_write_rgba_span(ctx
, &span
);
179 span
.array
->ChanType
= CHAN_TYPE
;
182 _mesa_free(convImage
);
190 copy_rgba_pixels(GLcontext
*ctx
, GLint srcx
, GLint srcy
,
191 GLint width
, GLint height
, GLint destx
, GLint desty
)
193 GLfloat
*tmpImage
, *p
;
194 GLint sy
, dy
, stepy
, row
;
195 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
197 GLuint transferOps
= ctx
->_ImageTransferState
;
200 if (!ctx
->ReadBuffer
->_ColorReadBuffer
) {
201 /* no readbuffer - OK */
205 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
206 copy_conv_rgba_pixels(ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
209 else if (ctx
->Pixel
.Convolution1DEnabled
) {
210 /* make sure we don't apply 1D convolution */
211 transferOps
&= ~(IMAGE_CONVOLUTION_BIT
|
212 IMAGE_POST_CONVOLUTION_SCALE_BIAS
);
215 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
216 overlapping
= regions_overlap(srcx
, srcy
, destx
, desty
, width
, height
,
217 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
220 overlapping
= GL_FALSE
;
223 /* Determine if copy should be done bottom-to-top or top-to-bottom */
224 if (!overlapping
&& srcy
< desty
) {
225 /* top-down max-to-min */
226 sy
= srcy
+ height
- 1;
227 dy
= desty
+ height
- 1;
231 /* bottom-up min-to-max */
237 INIT_SPAN(span
, GL_BITMAP
);
238 _swrast_span_default_attribs(ctx
, &span
);
239 span
.arrayMask
= SPAN_RGBA
;
240 span
.arrayAttribs
= FRAG_BIT_COL0
; /* we'll fill in COL0 attrib values */
243 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* sizeof(GLfloat
) * 4);
245 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels" );
248 /* read the source image as RGBA/float */
250 for (row
= 0; row
< height
; row
++) {
251 _swrast_read_rgba_span( ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
252 width
, srcx
, sy
+ row
, GL_FLOAT
, p
);
258 tmpImage
= NULL
; /* silence compiler warnings */
262 ASSERT(width
< MAX_WIDTH
);
264 for (row
= 0; row
< height
; row
++, sy
+= stepy
, dy
+= stepy
) {
265 GLvoid
*rgba
= span
.array
->attribs
[FRAG_ATTRIB_COL0
];
267 /* Get row/span of source pixels */
269 /* get from buffered image */
270 _mesa_memcpy(rgba
, p
, width
* sizeof(GLfloat
) * 4);
274 /* get from framebuffer */
275 _swrast_read_rgba_span( ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
276 width
, srcx
, sy
, GL_FLOAT
, rgba
);
280 _mesa_apply_rgba_transfer_ops(ctx
, transferOps
, width
,
281 (GLfloat (*)[4]) rgba
);
284 /* Write color span */
288 span
.array
->ChanType
= GL_FLOAT
;
290 _swrast_write_zoomed_rgba_span(ctx
, destx
, desty
, &span
, rgba
);
293 _swrast_write_rgba_span(ctx
, &span
);
297 span
.array
->ChanType
= CHAN_TYPE
; /* restore */
300 _mesa_free(tmpImage
);
305 copy_ci_pixels( GLcontext
*ctx
, GLint srcx
, GLint srcy
,
306 GLint width
, GLint height
,
307 GLint destx
, GLint desty
)
312 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
316 if (!ctx
->ReadBuffer
->_ColorReadBuffer
) {
317 /* no readbuffer - OK */
321 INIT_SPAN(span
, GL_BITMAP
);
322 _swrast_span_default_attribs(ctx
, &span
);
323 span
.arrayMask
= SPAN_INDEX
;
325 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
326 overlapping
= regions_overlap(srcx
, srcy
, destx
, desty
, width
, height
,
327 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
330 overlapping
= GL_FALSE
;
333 /* Determine if copy should be bottom-to-top or top-to-bottom */
334 if (!overlapping
&& srcy
< desty
) {
335 /* top-down max-to-min */
336 sy
= srcy
+ height
- 1;
337 dy
= desty
+ height
- 1;
341 /* bottom-up min-to-max */
349 tmpImage
= (GLuint
*) _mesa_malloc(width
* height
* sizeof(GLuint
));
351 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels" );
356 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
357 _swrast_read_index_span( ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
358 width
, srcx
, ssy
, p
);
364 tmpImage
= NULL
; /* silence compiler warning */
368 for (j
= 0; j
< height
; j
++, sy
+= stepy
, dy
+= stepy
) {
369 /* Get color indexes */
371 _mesa_memcpy(span
.array
->index
, p
, width
* sizeof(GLuint
));
375 _swrast_read_index_span( ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
376 width
, srcx
, sy
, span
.array
->index
);
379 if (ctx
->_ImageTransferState
)
380 _mesa_apply_ci_transfer_ops(ctx
, ctx
->_ImageTransferState
,
381 width
, span
.array
->index
);
383 /* write color indexes */
388 _swrast_write_zoomed_index_span(ctx
, destx
, desty
, &span
);
390 _swrast_write_index_span(ctx
, &span
);
394 _mesa_free(tmpImage
);
399 * Convert floating point Z values to integer Z values with pixel transfer's
403 scale_and_bias_z(GLcontext
*ctx
, GLuint width
,
404 const GLfloat depth
[], GLuint z
[])
406 const GLuint depthMax
= ctx
->DrawBuffer
->_DepthMax
;
409 if (depthMax
<= 0xffffff &&
410 ctx
->Pixel
.DepthScale
== 1.0 &&
411 ctx
->Pixel
.DepthBias
== 0.0) {
412 /* no scale or bias and no clamping and no worry of overflow */
413 const GLfloat depthMaxF
= ctx
->DrawBuffer
->_DepthMaxF
;
414 for (i
= 0; i
< width
; i
++) {
415 z
[i
] = (GLuint
) (depth
[i
] * depthMaxF
);
419 /* need to be careful with overflow */
420 const GLdouble depthMaxF
= ctx
->DrawBuffer
->_DepthMaxF
;
421 for (i
= 0; i
< width
; i
++) {
422 GLdouble d
= depth
[i
] * ctx
->Pixel
.DepthScale
+ ctx
->Pixel
.DepthBias
;
423 d
= CLAMP(d
, 0.0, 1.0) * depthMaxF
;
438 copy_depth_pixels( GLcontext
*ctx
, GLint srcx
, GLint srcy
,
439 GLint width
, GLint height
,
440 GLint destx
, GLint desty
)
442 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
443 struct gl_renderbuffer
*readRb
= fb
->_DepthBuffer
;
444 GLfloat
*p
, *tmpImage
;
447 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
452 /* no readbuffer - OK */
456 INIT_SPAN(span
, GL_BITMAP
);
457 _swrast_span_default_attribs(ctx
, &span
);
458 span
.arrayMask
= SPAN_Z
;
460 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
461 overlapping
= regions_overlap(srcx
, srcy
, destx
, desty
, width
, height
,
462 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
465 overlapping
= GL_FALSE
;
468 /* Determine if copy should be bottom-to-top or top-to-bottom */
469 if (!overlapping
&& srcy
< desty
) {
470 /* top-down max-to-min */
471 sy
= srcy
+ height
- 1;
472 dy
= desty
+ height
- 1;
476 /* bottom-up min-to-max */
484 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* sizeof(GLfloat
));
486 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels" );
490 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
491 _swrast_read_depth_span_float(ctx
, readRb
, width
, srcx
, ssy
, p
);
497 tmpImage
= NULL
; /* silence compiler warning */
501 for (j
= 0; j
< height
; j
++, sy
+= stepy
, dy
+= stepy
) {
502 GLfloat depth
[MAX_WIDTH
];
503 /* get depth values */
505 _mesa_memcpy(depth
, p
, width
* sizeof(GLfloat
));
509 _swrast_read_depth_span_float(ctx
, readRb
, width
, srcx
, sy
, depth
);
512 /* apply scale and bias */
513 scale_and_bias_z(ctx
, width
, depth
, span
.array
->z
);
515 /* write depth values */
519 if (fb
->Visual
.rgbMode
) {
521 _swrast_write_zoomed_depth_span(ctx
, destx
, desty
, &span
);
523 _swrast_write_rgba_span(ctx
, &span
);
527 _swrast_write_zoomed_depth_span(ctx
, destx
, desty
, &span
);
529 _swrast_write_index_span(ctx
, &span
);
534 _mesa_free(tmpImage
);
540 copy_stencil_pixels( GLcontext
*ctx
, GLint srcx
, GLint srcy
,
541 GLint width
, GLint height
,
542 GLint destx
, GLint desty
)
544 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
545 struct gl_renderbuffer
*rb
= fb
->_StencilBuffer
;
548 GLstencil
*p
, *tmpImage
;
549 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
553 /* no readbuffer - OK */
557 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
558 overlapping
= regions_overlap(srcx
, srcy
, destx
, desty
, width
, height
,
559 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
562 overlapping
= GL_FALSE
;
565 /* Determine if copy should be bottom-to-top or top-to-bottom */
566 if (!overlapping
&& srcy
< desty
) {
567 /* top-down max-to-min */
568 sy
= srcy
+ height
- 1;
569 dy
= desty
+ height
- 1;
573 /* bottom-up min-to-max */
581 tmpImage
= (GLstencil
*) _mesa_malloc(width
* height
* sizeof(GLstencil
));
583 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels" );
587 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
588 _swrast_read_stencil_span( ctx
, rb
, width
, srcx
, ssy
, p
);
594 tmpImage
= NULL
; /* silence compiler warning */
598 for (j
= 0; j
< height
; j
++, sy
+= stepy
, dy
+= stepy
) {
599 GLstencil stencil
[MAX_WIDTH
];
601 /* Get stencil values */
603 _mesa_memcpy(stencil
, p
, width
* sizeof(GLstencil
));
607 _swrast_read_stencil_span( ctx
, rb
, width
, srcx
, sy
, stencil
);
610 _mesa_apply_stencil_transfer_ops(ctx
, width
, stencil
);
612 /* Write stencil values */
614 _swrast_write_zoomed_stencil_span(ctx
, destx
, desty
, width
,
618 _swrast_write_stencil_span( ctx
, width
, destx
, dy
, stencil
);
623 _mesa_free(tmpImage
);
628 * This isn't terribly efficient. If a driver really has combined
629 * depth/stencil buffers the driver should implement an optimized
630 * CopyPixels function.
633 copy_depth_stencil_pixels(GLcontext
*ctx
,
634 const GLint srcX
, const GLint srcY
,
635 const GLint width
, const GLint height
,
636 const GLint destX
, const GLint destY
)
638 struct gl_renderbuffer
*stencilReadRb
, *depthReadRb
, *depthDrawRb
;
641 GLstencil
*tempStencilImage
= NULL
, *stencilPtr
= NULL
;
642 GLfloat
*tempDepthImage
= NULL
, *depthPtr
= NULL
;
643 const GLfloat depthScale
= ctx
->DrawBuffer
->_DepthMaxF
;
644 const GLuint stencilMask
= ctx
->Stencil
.WriteMask
[0];
645 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
646 const GLboolean scaleOrBias
647 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
650 depthDrawRb
= ctx
->DrawBuffer
->_DepthBuffer
;
651 depthReadRb
= ctx
->ReadBuffer
->_DepthBuffer
;
652 stencilReadRb
= ctx
->ReadBuffer
->_StencilBuffer
;
656 ASSERT(stencilReadRb
);
658 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
659 overlapping
= regions_overlap(srcX
, srcY
, destX
, destY
, width
, height
,
660 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
663 overlapping
= GL_FALSE
;
666 /* Determine if copy should be bottom-to-top or top-to-bottom */
667 if (!overlapping
&& srcY
< destY
) {
668 /* top-down max-to-min */
669 sy
= srcY
+ height
- 1;
670 dy
= destY
+ height
- 1;
674 /* bottom-up min-to-max */
683 if (stencilMask
!= 0x0) {
685 = (GLstencil
*) _mesa_malloc(width
* height
* sizeof(GLstencil
));
686 if (!tempStencilImage
) {
687 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels");
691 /* get copy of stencil pixels */
692 stencilPtr
= tempStencilImage
;
693 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
694 _swrast_read_stencil_span(ctx
, stencilReadRb
,
695 width
, srcX
, ssy
, stencilPtr
);
698 stencilPtr
= tempStencilImage
;
701 if (ctx
->Depth
.Mask
) {
703 = (GLfloat
*) _mesa_malloc(width
* height
* sizeof(GLfloat
));
704 if (!tempDepthImage
) {
705 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels");
706 _mesa_free(tempStencilImage
);
710 /* get copy of depth pixels */
711 depthPtr
= tempDepthImage
;
712 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
713 _swrast_read_depth_span_float(ctx
, depthReadRb
,
714 width
, srcX
, ssy
, depthPtr
);
717 depthPtr
= tempDepthImage
;
721 for (j
= 0; j
< height
; j
++, sy
+= stepy
, dy
+= stepy
) {
722 if (stencilMask
!= 0x0) {
723 GLstencil stencil
[MAX_WIDTH
];
725 /* Get stencil values */
727 _mesa_memcpy(stencil
, stencilPtr
, width
* sizeof(GLstencil
));
731 _swrast_read_stencil_span(ctx
, stencilReadRb
,
732 width
, srcX
, sy
, stencil
);
735 _mesa_apply_stencil_transfer_ops(ctx
, width
, stencil
);
739 _swrast_write_zoomed_stencil_span(ctx
, destX
, destY
, width
,
743 _swrast_write_stencil_span( ctx
, width
, destX
, dy
, stencil
);
747 if (ctx
->Depth
.Mask
) {
748 GLfloat depth
[MAX_WIDTH
];
749 GLuint zVals32
[MAX_WIDTH
];
750 GLushort zVals16
[MAX_WIDTH
];
754 /* get depth values */
756 _mesa_memcpy(depth
, depthPtr
, width
* sizeof(GLfloat
));
760 _swrast_read_depth_span_float(ctx
, depthReadRb
,
761 width
, srcX
, sy
, depth
);
766 _mesa_scale_and_bias_depth(ctx
, width
, depth
);
768 /* convert to integer Z values */
769 if (depthDrawRb
->DataType
== GL_UNSIGNED_SHORT
) {
771 for (k
= 0; k
< width
; k
++)
772 zVals16
[k
] = (GLushort
) (depth
[k
] * depthScale
);
778 for (k
= 0; k
< width
; k
++)
779 zVals32
[k
] = (GLuint
) (depth
[k
] * depthScale
);
786 _swrast_write_zoomed_z_span(ctx
, destX
, destY
, width
,
790 _swrast_put_row(ctx
, depthDrawRb
, width
, destX
, dy
, zVals
, zBytes
);
795 if (tempStencilImage
)
796 _mesa_free(tempStencilImage
);
799 _mesa_free(tempDepthImage
);
805 * Try to do a fast copy pixels.
808 fast_copy_pixels(GLcontext
*ctx
,
809 GLint srcX
, GLint srcY
, GLsizei width
, GLsizei height
,
810 GLint dstX
, GLint dstY
, GLenum type
)
812 struct gl_framebuffer
*srcFb
= ctx
->ReadBuffer
;
813 struct gl_framebuffer
*dstFb
= ctx
->DrawBuffer
;
814 struct gl_renderbuffer
*srcRb
, *dstRb
;
817 if (SWRAST_CONTEXT(ctx
)->_RasterMask
!= 0x0 ||
818 ctx
->Pixel
.ZoomX
!= 1.0F
||
819 ctx
->Pixel
.ZoomY
!= 1.0F
||
820 ctx
->_ImageTransferState
) {
821 /* can't handle these */
825 if (type
== GL_COLOR
) {
826 if (dstFb
->_NumColorDrawBuffers
[0] != 1)
828 srcRb
= srcFb
->_ColorReadBuffer
;
829 dstRb
= dstFb
->_ColorDrawBuffers
[0][0];
831 else if (type
== GL_STENCIL
) {
832 srcRb
= srcFb
->_StencilBuffer
;
833 dstRb
= dstFb
->_StencilBuffer
;
835 else if (type
== GL_DEPTH
) {
836 srcRb
= srcFb
->_DepthBuffer
;
837 dstRb
= dstFb
->_DepthBuffer
;
840 ASSERT(type
== GL_DEPTH_STENCIL_EXT
);
842 srcRb
= srcFb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
843 dstRb
= dstFb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
846 /* src and dst renderbuffers must be same format and type */
847 if (!srcRb
|| !dstRb
||
848 srcRb
->DataType
!= dstRb
->DataType
||
849 srcRb
->_BaseFormat
!= dstRb
->_BaseFormat
) {
853 /* clipping not supported */
854 if (srcX
< 0 || srcX
+ width
> (GLint
) srcFb
->Width
||
855 srcY
< 0 || srcY
+ height
> (GLint
) srcFb
->Height
||
856 dstX
< dstFb
->_Xmin
|| dstX
+ width
> dstFb
->_Xmax
||
857 dstY
< dstFb
->_Ymin
|| dstY
+ height
> dstFb
->_Ymax
) {
861 /* overlapping src/dst doesn't matter, just determine Y direction */
863 /* top-down max-to-min */
864 srcY
= srcY
+ height
- 1;
865 dstY
= dstY
+ height
- 1;
869 /* bottom-up min-to-max */
873 for (row
= 0; row
< height
; row
++) {
874 GLuint temp
[MAX_WIDTH
][4];
875 srcRb
->GetRow(ctx
, srcRb
, width
, srcX
, srcY
, temp
);
876 dstRb
->PutRow(ctx
, dstRb
, width
, dstX
, dstY
, temp
, NULL
);
886 * Do software-based glCopyPixels.
887 * By time we get here, all parameters will have been error-checked.
890 _swrast_CopyPixels( GLcontext
*ctx
,
891 GLint srcx
, GLint srcy
, GLsizei width
, GLsizei height
,
892 GLint destx
, GLint desty
, GLenum type
)
894 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
895 RENDER_START(swrast
,ctx
);
897 if (swrast
->NewState
)
898 _swrast_validate_derived( ctx
);
900 if (!fast_copy_pixels(ctx
, srcx
, srcy
, width
, height
, destx
, desty
, type
)) {
903 if (ctx
->Visual
.rgbMode
) {
904 copy_rgba_pixels( ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
907 copy_ci_pixels( ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
911 copy_depth_pixels( ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
914 copy_stencil_pixels( ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
916 case GL_DEPTH_STENCIL_EXT
:
917 copy_depth_stencil_pixels(ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
920 _mesa_problem(ctx
, "unexpected type in _swrast_CopyPixels");
924 RENDER_FINISH(swrast
,ctx
);