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.
26 #include "main/glheader.h"
27 #include "main/context.h"
28 #include "main/colormac.h"
29 #include "main/condrender.h"
30 #include "main/convolve.h"
31 #include "main/histogram.h"
32 #include "main/image.h"
33 #include "main/macros.h"
34 #include "main/imports.h"
35 #include "main/pixel.h"
37 #include "s_context.h"
40 #include "s_stencil.h"
46 * Determine if there's overlap in an image copy.
47 * This test also compensates for the fact that copies are done from
48 * bottom to top and overlaps can sometimes be handled correctly
49 * without making a temporary image copy.
50 * \return GL_TRUE if the regions overlap, GL_FALSE otherwise.
53 regions_overlap(GLint srcx
, GLint srcy
,
54 GLint dstx
, GLint dsty
,
55 GLint width
, GLint height
,
56 GLfloat zoomX
, GLfloat zoomY
)
58 if (zoomX
== 1.0 && zoomY
== 1.0) {
60 if (srcx
>= dstx
+ width
|| (srcx
+ width
<= dstx
)) {
63 else if (srcy
< dsty
) { /* this is OK */
66 else if (srcy
> dsty
+ height
) {
74 /* add one pixel of slop when zooming, just to be safe */
75 if (srcx
> (dstx
+ ((zoomX
> 0.0F
) ? (width
* zoomX
+ 1.0F
) : 0.0F
))) {
76 /* src is completely right of dest */
79 else if (srcx
+ width
+ 1.0F
< dstx
+ ((zoomX
> 0.0F
) ? 0.0F
: (width
* zoomX
))) {
80 /* src is completely left of dest */
83 else if ((srcy
< dsty
) && (srcy
+ height
< dsty
+ (height
* zoomY
))) {
84 /* src is completely below dest */
87 else if ((srcy
> dsty
) && (srcy
+ height
> dsty
+ (height
* zoomY
))) {
88 /* src is completely above dest */
99 * RGBA copypixels with convolution.
102 copy_conv_rgba_pixels(GLcontext
*ctx
, GLint srcx
, GLint srcy
,
103 GLint width
, GLint height
, GLint destx
, GLint desty
)
106 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
107 const GLbitfield transferOps
= ctx
->_ImageTransferState
;
108 const GLboolean sink
= (ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
)
109 || (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
);
110 GLfloat
*dest
, *tmpImage
, *convImage
;
113 INIT_SPAN(span
, GL_BITMAP
);
114 _swrast_span_default_attribs(ctx
, &span
);
115 span
.arrayMask
= SPAN_RGBA
;
116 span
.arrayAttribs
= FRAG_BIT_COL0
;
118 /* allocate space for GLfloat image */
119 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
121 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels");
124 convImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
126 _mesa_free(tmpImage
);
127 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels");
131 /* read source image as float/RGBA */
133 for (row
= 0; row
< height
; row
++) {
134 _swrast_read_rgba_span(ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
135 width
, srcx
, srcy
+ row
, GL_FLOAT
, dest
);
139 /* do the image transfer ops which preceed convolution */
140 for (row
= 0; row
< height
; row
++) {
141 GLfloat (*rgba
)[4] = (GLfloat (*)[4]) (tmpImage
+ row
* width
* 4);
142 _mesa_apply_rgba_transfer_ops(ctx
,
143 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
,
148 if (ctx
->Pixel
.Convolution2DEnabled
) {
149 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
152 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
153 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
155 _mesa_free(tmpImage
);
157 /* do remaining post-convolution image transfer ops */
158 for (row
= 0; row
< height
; row
++) {
159 GLfloat (*rgba
)[4] = (GLfloat (*)[4]) (convImage
+ row
* width
* 4);
160 _mesa_apply_rgba_transfer_ops(ctx
,
161 transferOps
& IMAGE_POST_CONVOLUTION_BITS
,
166 /* write the new image */
167 for (row
= 0; row
< height
; row
++) {
168 const GLfloat
*src
= convImage
+ row
* width
* 4;
169 GLfloat
*rgba
= (GLfloat
*) span
.array
->attribs
[FRAG_ATTRIB_COL0
];
171 /* copy convolved colors into span array */
172 _mesa_memcpy(rgba
, src
, width
* 4 * sizeof(GLfloat
));
176 span
.y
= desty
+ row
;
178 span
.array
->ChanType
= GL_FLOAT
;
180 _swrast_write_zoomed_rgba_span(ctx
, destx
, desty
, &span
, rgba
);
183 _swrast_write_rgba_span(ctx
, &span
);
187 span
.array
->ChanType
= CHAN_TYPE
;
190 _mesa_free(convImage
);
198 copy_rgba_pixels(GLcontext
*ctx
, GLint srcx
, GLint srcy
,
199 GLint width
, GLint height
, GLint destx
, GLint desty
)
201 GLfloat
*tmpImage
, *p
;
202 GLint sy
, dy
, stepy
, row
;
203 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
205 GLuint transferOps
= ctx
->_ImageTransferState
;
208 if (!ctx
->ReadBuffer
->_ColorReadBuffer
) {
209 /* no readbuffer - OK */
213 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
214 copy_conv_rgba_pixels(ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
217 else if (ctx
->Pixel
.Convolution1DEnabled
) {
218 /* make sure we don't apply 1D convolution */
219 transferOps
&= ~(IMAGE_CONVOLUTION_BIT
|
220 IMAGE_POST_CONVOLUTION_SCALE_BIAS
);
223 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
224 overlapping
= regions_overlap(srcx
, srcy
, destx
, desty
, width
, height
,
225 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
228 overlapping
= GL_FALSE
;
231 /* Determine if copy should be done bottom-to-top or top-to-bottom */
232 if (!overlapping
&& srcy
< desty
) {
233 /* top-down max-to-min */
234 sy
= srcy
+ height
- 1;
235 dy
= desty
+ height
- 1;
239 /* bottom-up min-to-max */
245 INIT_SPAN(span
, GL_BITMAP
);
246 _swrast_span_default_attribs(ctx
, &span
);
247 span
.arrayMask
= SPAN_RGBA
;
248 span
.arrayAttribs
= FRAG_BIT_COL0
; /* we'll fill in COL0 attrib values */
251 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* sizeof(GLfloat
) * 4);
253 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels" );
256 /* read the source image as RGBA/float */
258 for (row
= 0; row
< height
; row
++) {
259 _swrast_read_rgba_span( ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
260 width
, srcx
, sy
+ row
, GL_FLOAT
, p
);
266 tmpImage
= NULL
; /* silence compiler warnings */
270 ASSERT(width
< MAX_WIDTH
);
272 for (row
= 0; row
< height
; row
++, sy
+= stepy
, dy
+= stepy
) {
273 GLvoid
*rgba
= span
.array
->attribs
[FRAG_ATTRIB_COL0
];
275 /* Get row/span of source pixels */
277 /* get from buffered image */
278 _mesa_memcpy(rgba
, p
, width
* sizeof(GLfloat
) * 4);
282 /* get from framebuffer */
283 _swrast_read_rgba_span( ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
284 width
, srcx
, sy
, GL_FLOAT
, rgba
);
288 _mesa_apply_rgba_transfer_ops(ctx
, transferOps
, width
,
289 (GLfloat (*)[4]) rgba
);
292 /* Write color span */
296 span
.array
->ChanType
= GL_FLOAT
;
298 _swrast_write_zoomed_rgba_span(ctx
, destx
, desty
, &span
, rgba
);
301 _swrast_write_rgba_span(ctx
, &span
);
305 span
.array
->ChanType
= CHAN_TYPE
; /* restore */
308 _mesa_free(tmpImage
);
313 copy_ci_pixels( GLcontext
*ctx
, GLint srcx
, GLint srcy
,
314 GLint width
, GLint height
,
315 GLint destx
, GLint desty
)
320 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
324 if (!ctx
->ReadBuffer
->_ColorReadBuffer
) {
325 /* no readbuffer - OK */
329 INIT_SPAN(span
, GL_BITMAP
);
330 _swrast_span_default_attribs(ctx
, &span
);
331 span
.arrayMask
= SPAN_INDEX
;
333 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
334 overlapping
= regions_overlap(srcx
, srcy
, destx
, desty
, width
, height
,
335 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
338 overlapping
= GL_FALSE
;
341 /* Determine if copy should be bottom-to-top or top-to-bottom */
342 if (!overlapping
&& srcy
< desty
) {
343 /* top-down max-to-min */
344 sy
= srcy
+ height
- 1;
345 dy
= desty
+ height
- 1;
349 /* bottom-up min-to-max */
357 tmpImage
= (GLuint
*) _mesa_malloc(width
* height
* sizeof(GLuint
));
359 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels" );
364 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
365 _swrast_read_index_span( ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
366 width
, srcx
, ssy
, p
);
372 tmpImage
= NULL
; /* silence compiler warning */
376 for (j
= 0; j
< height
; j
++, sy
+= stepy
, dy
+= stepy
) {
377 /* Get color indexes */
379 _mesa_memcpy(span
.array
->index
, p
, width
* sizeof(GLuint
));
383 _swrast_read_index_span( ctx
, ctx
->ReadBuffer
->_ColorReadBuffer
,
384 width
, srcx
, sy
, span
.array
->index
);
387 if (ctx
->_ImageTransferState
)
388 _mesa_apply_ci_transfer_ops(ctx
, ctx
->_ImageTransferState
,
389 width
, span
.array
->index
);
391 /* write color indexes */
396 _swrast_write_zoomed_index_span(ctx
, destx
, desty
, &span
);
398 _swrast_write_index_span(ctx
, &span
);
402 _mesa_free(tmpImage
);
407 * Convert floating point Z values to integer Z values with pixel transfer's
411 scale_and_bias_z(GLcontext
*ctx
, GLuint width
,
412 const GLfloat depth
[], GLuint z
[])
414 const GLuint depthMax
= ctx
->DrawBuffer
->_DepthMax
;
417 if (depthMax
<= 0xffffff &&
418 ctx
->Pixel
.DepthScale
== 1.0 &&
419 ctx
->Pixel
.DepthBias
== 0.0) {
420 /* no scale or bias and no clamping and no worry of overflow */
421 const GLfloat depthMaxF
= ctx
->DrawBuffer
->_DepthMaxF
;
422 for (i
= 0; i
< width
; i
++) {
423 z
[i
] = (GLuint
) (depth
[i
] * depthMaxF
);
427 /* need to be careful with overflow */
428 const GLdouble depthMaxF
= ctx
->DrawBuffer
->_DepthMaxF
;
429 for (i
= 0; i
< width
; i
++) {
430 GLdouble d
= depth
[i
] * ctx
->Pixel
.DepthScale
+ ctx
->Pixel
.DepthBias
;
431 d
= CLAMP(d
, 0.0, 1.0) * depthMaxF
;
446 copy_depth_pixels( GLcontext
*ctx
, GLint srcx
, GLint srcy
,
447 GLint width
, GLint height
,
448 GLint destx
, GLint desty
)
450 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
451 struct gl_renderbuffer
*readRb
= fb
->_DepthBuffer
;
452 GLfloat
*p
, *tmpImage
;
455 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
460 /* no readbuffer - OK */
464 INIT_SPAN(span
, GL_BITMAP
);
465 _swrast_span_default_attribs(ctx
, &span
);
466 span
.arrayMask
= SPAN_Z
;
468 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
469 overlapping
= regions_overlap(srcx
, srcy
, destx
, desty
, width
, height
,
470 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
473 overlapping
= GL_FALSE
;
476 /* Determine if copy should be bottom-to-top or top-to-bottom */
477 if (!overlapping
&& srcy
< desty
) {
478 /* top-down max-to-min */
479 sy
= srcy
+ height
- 1;
480 dy
= desty
+ height
- 1;
484 /* bottom-up min-to-max */
492 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* sizeof(GLfloat
));
494 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels" );
498 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
499 _swrast_read_depth_span_float(ctx
, readRb
, width
, srcx
, ssy
, p
);
505 tmpImage
= NULL
; /* silence compiler warning */
509 for (j
= 0; j
< height
; j
++, sy
+= stepy
, dy
+= stepy
) {
510 GLfloat depth
[MAX_WIDTH
];
511 /* get depth values */
513 _mesa_memcpy(depth
, p
, width
* sizeof(GLfloat
));
517 _swrast_read_depth_span_float(ctx
, readRb
, width
, srcx
, sy
, depth
);
520 /* apply scale and bias */
521 scale_and_bias_z(ctx
, width
, depth
, span
.array
->z
);
523 /* write depth values */
527 if (fb
->Visual
.rgbMode
) {
529 _swrast_write_zoomed_depth_span(ctx
, destx
, desty
, &span
);
531 _swrast_write_rgba_span(ctx
, &span
);
535 _swrast_write_zoomed_depth_span(ctx
, destx
, desty
, &span
);
537 _swrast_write_index_span(ctx
, &span
);
542 _mesa_free(tmpImage
);
548 copy_stencil_pixels( GLcontext
*ctx
, GLint srcx
, GLint srcy
,
549 GLint width
, GLint height
,
550 GLint destx
, GLint desty
)
552 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
553 struct gl_renderbuffer
*rb
= fb
->_StencilBuffer
;
556 GLstencil
*p
, *tmpImage
;
557 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
561 /* no readbuffer - OK */
565 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
566 overlapping
= regions_overlap(srcx
, srcy
, destx
, desty
, width
, height
,
567 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
570 overlapping
= GL_FALSE
;
573 /* Determine if copy should be bottom-to-top or top-to-bottom */
574 if (!overlapping
&& srcy
< desty
) {
575 /* top-down max-to-min */
576 sy
= srcy
+ height
- 1;
577 dy
= desty
+ height
- 1;
581 /* bottom-up min-to-max */
589 tmpImage
= (GLstencil
*) _mesa_malloc(width
* height
* sizeof(GLstencil
));
591 _mesa_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels" );
595 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
596 _swrast_read_stencil_span( ctx
, rb
, width
, srcx
, ssy
, p
);
602 tmpImage
= NULL
; /* silence compiler warning */
606 for (j
= 0; j
< height
; j
++, sy
+= stepy
, dy
+= stepy
) {
607 GLstencil stencil
[MAX_WIDTH
];
609 /* Get stencil values */
611 _mesa_memcpy(stencil
, p
, width
* sizeof(GLstencil
));
615 _swrast_read_stencil_span( ctx
, rb
, width
, srcx
, sy
, stencil
);
618 _mesa_apply_stencil_transfer_ops(ctx
, width
, stencil
);
620 /* Write stencil values */
622 _swrast_write_zoomed_stencil_span(ctx
, destx
, desty
, width
,
626 _swrast_write_stencil_span( ctx
, width
, destx
, dy
, stencil
);
631 _mesa_free(tmpImage
);
636 * This isn't terribly efficient. If a driver really has combined
637 * depth/stencil buffers the driver should implement an optimized
638 * CopyPixels function.
641 copy_depth_stencil_pixels(GLcontext
*ctx
,
642 const GLint srcX
, const GLint srcY
,
643 const GLint width
, const GLint height
,
644 const GLint destX
, const GLint destY
)
646 struct gl_renderbuffer
*stencilReadRb
, *depthReadRb
, *depthDrawRb
;
649 GLstencil
*tempStencilImage
= NULL
, *stencilPtr
= NULL
;
650 GLfloat
*tempDepthImage
= NULL
, *depthPtr
= NULL
;
651 const GLfloat depthScale
= ctx
->DrawBuffer
->_DepthMaxF
;
652 const GLuint stencilMask
= ctx
->Stencil
.WriteMask
[0];
653 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0F
|| ctx
->Pixel
.ZoomY
!= 1.0F
;
654 const GLboolean scaleOrBias
655 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
658 depthDrawRb
= ctx
->DrawBuffer
->_DepthBuffer
;
659 depthReadRb
= ctx
->ReadBuffer
->_DepthBuffer
;
660 stencilReadRb
= ctx
->ReadBuffer
->_StencilBuffer
;
664 ASSERT(stencilReadRb
);
666 if (ctx
->DrawBuffer
== ctx
->ReadBuffer
) {
667 overlapping
= regions_overlap(srcX
, srcY
, destX
, destY
, width
, height
,
668 ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
);
671 overlapping
= GL_FALSE
;
674 /* Determine if copy should be bottom-to-top or top-to-bottom */
675 if (!overlapping
&& srcY
< destY
) {
676 /* top-down max-to-min */
677 sy
= srcY
+ height
- 1;
678 dy
= destY
+ height
- 1;
682 /* bottom-up min-to-max */
691 if (stencilMask
!= 0x0) {
693 = (GLstencil
*) _mesa_malloc(width
* height
* sizeof(GLstencil
));
694 if (!tempStencilImage
) {
695 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels");
699 /* get copy of stencil pixels */
700 stencilPtr
= tempStencilImage
;
701 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
702 _swrast_read_stencil_span(ctx
, stencilReadRb
,
703 width
, srcX
, ssy
, stencilPtr
);
706 stencilPtr
= tempStencilImage
;
709 if (ctx
->Depth
.Mask
) {
711 = (GLfloat
*) _mesa_malloc(width
* height
* sizeof(GLfloat
));
712 if (!tempDepthImage
) {
713 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyPixels");
714 _mesa_free(tempStencilImage
);
718 /* get copy of depth pixels */
719 depthPtr
= tempDepthImage
;
720 for (j
= 0; j
< height
; j
++, ssy
+= stepy
) {
721 _swrast_read_depth_span_float(ctx
, depthReadRb
,
722 width
, srcX
, ssy
, depthPtr
);
725 depthPtr
= tempDepthImage
;
729 for (j
= 0; j
< height
; j
++, sy
+= stepy
, dy
+= stepy
) {
730 if (stencilMask
!= 0x0) {
731 GLstencil stencil
[MAX_WIDTH
];
733 /* Get stencil values */
735 _mesa_memcpy(stencil
, stencilPtr
, width
* sizeof(GLstencil
));
739 _swrast_read_stencil_span(ctx
, stencilReadRb
,
740 width
, srcX
, sy
, stencil
);
743 _mesa_apply_stencil_transfer_ops(ctx
, width
, stencil
);
747 _swrast_write_zoomed_stencil_span(ctx
, destX
, destY
, width
,
751 _swrast_write_stencil_span( ctx
, width
, destX
, dy
, stencil
);
755 if (ctx
->Depth
.Mask
) {
756 GLfloat depth
[MAX_WIDTH
];
757 GLuint zVals32
[MAX_WIDTH
];
758 GLushort zVals16
[MAX_WIDTH
];
762 /* get depth values */
764 _mesa_memcpy(depth
, depthPtr
, width
* sizeof(GLfloat
));
768 _swrast_read_depth_span_float(ctx
, depthReadRb
,
769 width
, srcX
, sy
, depth
);
774 _mesa_scale_and_bias_depth(ctx
, width
, depth
);
776 /* convert to integer Z values */
777 if (depthDrawRb
->DataType
== GL_UNSIGNED_SHORT
) {
779 for (k
= 0; k
< width
; k
++)
780 zVals16
[k
] = (GLushort
) (depth
[k
] * depthScale
);
786 for (k
= 0; k
< width
; k
++)
787 zVals32
[k
] = (GLuint
) (depth
[k
] * depthScale
);
794 _swrast_write_zoomed_z_span(ctx
, destX
, destY
, width
,
798 _swrast_put_row(ctx
, depthDrawRb
, width
, destX
, dy
, zVals
, zBytes
);
803 if (tempStencilImage
)
804 _mesa_free(tempStencilImage
);
807 _mesa_free(tempDepthImage
);
813 * Try to do a fast copy pixels.
816 fast_copy_pixels(GLcontext
*ctx
,
817 GLint srcX
, GLint srcY
, GLsizei width
, GLsizei height
,
818 GLint dstX
, GLint dstY
, GLenum type
)
820 struct gl_framebuffer
*srcFb
= ctx
->ReadBuffer
;
821 struct gl_framebuffer
*dstFb
= ctx
->DrawBuffer
;
822 struct gl_renderbuffer
*srcRb
, *dstRb
;
825 if (SWRAST_CONTEXT(ctx
)->_RasterMask
!= 0x0 ||
826 ctx
->Pixel
.ZoomX
!= 1.0F
||
827 ctx
->Pixel
.ZoomY
!= 1.0F
||
828 ctx
->_ImageTransferState
) {
829 /* can't handle these */
833 if (type
== GL_COLOR
) {
834 if (dstFb
->_NumColorDrawBuffers
!= 1)
836 srcRb
= srcFb
->_ColorReadBuffer
;
837 dstRb
= dstFb
->_ColorDrawBuffers
[0];
839 else if (type
== GL_STENCIL
) {
840 srcRb
= srcFb
->_StencilBuffer
;
841 dstRb
= dstFb
->_StencilBuffer
;
843 else if (type
== GL_DEPTH
) {
844 srcRb
= srcFb
->_DepthBuffer
;
845 dstRb
= dstFb
->_DepthBuffer
;
848 ASSERT(type
== GL_DEPTH_STENCIL_EXT
);
850 srcRb
= srcFb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
851 dstRb
= dstFb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
854 /* src and dst renderbuffers must be same format and type */
855 if (!srcRb
|| !dstRb
||
856 srcRb
->DataType
!= dstRb
->DataType
||
857 srcRb
->_BaseFormat
!= dstRb
->_BaseFormat
) {
861 /* clipping not supported */
862 if (srcX
< 0 || srcX
+ width
> (GLint
) srcFb
->Width
||
863 srcY
< 0 || srcY
+ height
> (GLint
) srcFb
->Height
||
864 dstX
< dstFb
->_Xmin
|| dstX
+ width
> dstFb
->_Xmax
||
865 dstY
< dstFb
->_Ymin
|| dstY
+ height
> dstFb
->_Ymax
) {
869 /* overlapping src/dst doesn't matter, just determine Y direction */
871 /* top-down max-to-min */
872 srcY
= srcY
+ height
- 1;
873 dstY
= dstY
+ height
- 1;
877 /* bottom-up min-to-max */
881 for (row
= 0; row
< height
; row
++) {
882 GLuint temp
[MAX_WIDTH
][4];
883 srcRb
->GetRow(ctx
, srcRb
, width
, srcX
, srcY
, temp
);
884 dstRb
->PutRow(ctx
, dstRb
, width
, dstX
, dstY
, temp
, NULL
);
894 * Do software-based glCopyPixels.
895 * By time we get here, all parameters will have been error-checked.
898 _swrast_CopyPixels( GLcontext
*ctx
,
899 GLint srcx
, GLint srcy
, GLsizei width
, GLsizei height
,
900 GLint destx
, GLint desty
, GLenum type
)
902 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
903 swrast_render_start(ctx
);
905 if (!_mesa_check_conditional_render(ctx
))
906 return; /* don't copy */
908 if (swrast
->NewState
)
909 _swrast_validate_derived( ctx
);
911 if (!fast_copy_pixels(ctx
, srcx
, srcy
, width
, height
, destx
, desty
, type
)) {
914 if (ctx
->Visual
.rgbMode
) {
915 copy_rgba_pixels( ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
918 copy_ci_pixels( ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
922 copy_depth_pixels( ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
925 copy_stencil_pixels( ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
927 case GL_DEPTH_STENCIL_EXT
:
928 copy_depth_stencil_pixels(ctx
, srcx
, srcy
, width
, height
, destx
, desty
);
931 _mesa_problem(ctx
, "unexpected type in _swrast_CopyPixels");
935 swrast_render_finish(ctx
);