1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Mesa 3-D graphics library
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Version:  7.1
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"),
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or sell copies of the Software, and to permit persons to whom the
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software is furnished to do so, subject to the following conditions:
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice shall be included
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * in all copies or substantial portions of the Software.
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/glheader.h"
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/context.h"
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/colormac.h"
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/condrender.h"
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/macros.h"
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/pixeltransfer.h"
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/imports.h"
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "s_context.h"
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "s_depth.h"
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "s_span.h"
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "s_stencil.h"
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "s_zoom.h"
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Determine if there's overlap in an image copy.
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This test also compensates for the fact that copies are done from
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * bottom to top and overlaps can sometimes be handled correctly
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * without making a temporary image copy.
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \return GL_TRUE if the regions overlap, GL_FALSE otherwise.
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic GLboolean
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgregions_overlap(GLint srcx, GLint srcy,
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                GLint dstx, GLint dsty,
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                GLint width, GLint height,
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                GLfloat zoomX, GLfloat zoomY)
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (zoomX == 1.0 && zoomY == 1.0) {
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* no zoom */
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (srcx >= dstx + width || (srcx + width <= dstx)) {
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_FALSE;
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else if (srcy < dsty) { /* this is OK */
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_FALSE;
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else if (srcy > dsty + height) {
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_FALSE;
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_TRUE;
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* add one pixel of slop when zooming, just to be safe */
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (srcx > (dstx + ((zoomX > 0.0F) ? (width * zoomX + 1.0F) : 0.0F))) {
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* src is completely right of dest */
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_FALSE;
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else if (srcx + width + 1.0F < dstx + ((zoomX > 0.0F) ? 0.0F : (width * zoomX))) {
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* src is completely left of dest */
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_FALSE;
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else if ((srcy < dsty) && (srcy + height < dsty + (height * zoomY))) {
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* src is completely below dest */
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_FALSE;
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else if ((srcy > dsty) && (srcy + height > dsty + (height * zoomY))) {
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* src is completely above dest */
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_FALSE;
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_TRUE;
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * RGBA copypixels
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcopy_rgba_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 GLint width, GLint height, GLint destx, GLint desty)
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLfloat *tmpImage, *p;
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint sy, dy, stepy, row;
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint overlapping;
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLuint transferOps = ctx->_ImageTransferState;
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   SWspan span;
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!ctx->ReadBuffer->_ColorReadBuffer) {
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* no readbuffer - OK */
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ctx->DrawBuffer == ctx->ReadBuffer) {
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      overlapping = GL_FALSE;
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Determine if copy should be done bottom-to-top or top-to-bottom */
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!overlapping && srcy < desty) {
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* top-down  max-to-min */
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sy = srcy + height - 1;
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dy = desty + height - 1;
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      stepy = -1;
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* bottom-up  min-to-max */
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sy = srcy;
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dy = desty;
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      stepy = 1;
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   INIT_SPAN(span, GL_BITMAP);
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _swrast_span_default_attribs(ctx, &span);
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   span.arrayMask = SPAN_RGBA;
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   span.arrayAttribs = FRAG_BIT_COL0; /* we'll fill in COL0 attrib values */
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (overlapping) {
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tmpImage = (GLfloat *) malloc(width * height * sizeof(GLfloat) * 4);
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!tmpImage) {
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return;
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* read the source image as RGBA/float */
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      p = tmpImage;
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (row = 0; row < height; row++) {
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 width, srcx, sy + row, p );
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p += width * 4;
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      p = tmpImage;
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tmpImage = NULL;  /* silence compiler warnings */
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      p = NULL;
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ASSERT(width < SWRAST_MAX_WIDTH);
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (row = 0; row < height; row++, sy += stepy, dy += stepy) {
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLvoid *rgba = span.array->attribs[FRAG_ATTRIB_COL0];
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Get row/span of source pixels */
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (overlapping) {
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* get from buffered image */
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         memcpy(rgba, p, width * sizeof(GLfloat) * 4);
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p += width * 4;
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* get from framebuffer */
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 width, srcx, sy, rgba );
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (transferOps) {
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _mesa_apply_rgba_transfer_ops(ctx, transferOps, width,
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       (GLfloat (*)[4]) rgba);
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Write color span */
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      span.x = destx;
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      span.y = dy;
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      span.end = width;
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      span.array->ChanType = GL_FLOAT;
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (zoom) {
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, rgba);
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _swrast_write_rgba_span(ctx, &span);
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   span.array->ChanType = CHAN_TYPE; /* restore */
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (overlapping)
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      free(tmpImage);
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Convert floating point Z values to integer Z values with pixel transfer's
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Z scale and bias.
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgscale_and_bias_z(struct gl_context *ctx, GLuint width,
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 const GLfloat depth[], GLuint z[])
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLuint i;
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (depthMax <= 0xffffff &&
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       ctx->Pixel.DepthScale == 1.0 &&
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       ctx->Pixel.DepthBias == 0.0) {
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* no scale or bias and no clamping and no worry of overflow */
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const GLfloat depthMaxF = ctx->DrawBuffer->_DepthMaxF;
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < width; i++) {
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         z[i] = (GLuint) (depth[i] * depthMaxF);
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* need to be careful with overflow */
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const GLdouble depthMaxF = ctx->DrawBuffer->_DepthMaxF;
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < width; i++) {
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GLdouble d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         d = CLAMP(d, 0.0, 1.0) * depthMaxF;
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (d >= depthMaxF)
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            z[i] = depthMax;
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         else
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            z[i] = (GLuint) d;
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * TODO: Optimize!!!!
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcopy_depth_pixels( struct gl_context *ctx, GLint srcx, GLint srcy,
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                   GLint width, GLint height,
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                   GLint destx, GLint desty )
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_framebuffer *fb = ctx->ReadBuffer;
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_renderbuffer *readRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLfloat *p, *tmpImage, *depth;
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint sy, dy, stepy;
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint j;
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint overlapping;
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   SWspan span;
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!readRb) {
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* no readbuffer - OK */
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   INIT_SPAN(span, GL_BITMAP);
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _swrast_span_default_attribs(ctx, &span);
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   span.arrayMask = SPAN_Z;
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ctx->DrawBuffer == ctx->ReadBuffer) {
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      overlapping = GL_FALSE;
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Determine if copy should be bottom-to-top or top-to-bottom */
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!overlapping && srcy < desty) {
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* top-down  max-to-min */
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sy = srcy + height - 1;
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dy = desty + height - 1;
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      stepy = -1;
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* bottom-up  min-to-max */
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sy = srcy;
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dy = desty;
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      stepy = 1;
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (overlapping) {
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLint ssy = sy;
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tmpImage = (GLfloat *) malloc(width * height * sizeof(GLfloat));
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!tmpImage) {
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return;
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      p = tmpImage;
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (j = 0; j < height; j++, ssy += stepy) {
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _swrast_read_depth_span_float(ctx, readRb, width, srcx, ssy, p);
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p += width;
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      p = tmpImage;
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tmpImage = NULL;  /* silence compiler warning */
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      p = NULL;
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   depth = (GLfloat *) malloc(width * sizeof(GLfloat));
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!depth) {
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels()");
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      goto end;
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* get depth values */
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (overlapping) {
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         memcpy(depth, p, width * sizeof(GLfloat));
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p += width;
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _swrast_read_depth_span_float(ctx, readRb, width, srcx, sy, depth);
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* apply scale and bias */
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      scale_and_bias_z(ctx, width, depth, span.array->z);
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* write depth values */
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      span.x = destx;
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      span.y = dy;
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      span.end = width;
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (zoom)
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _swrast_write_zoomed_depth_span(ctx, destx, desty, &span);
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _swrast_write_rgba_span(ctx, &span);
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   free(depth);
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgend:
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (overlapping)
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      free(tmpImage);
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcopy_stencil_pixels( struct gl_context *ctx, GLint srcx, GLint srcy,
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     GLint width, GLint height,
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     GLint destx, GLint desty )
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_framebuffer *fb = ctx->ReadBuffer;
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint sy, dy, stepy;
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint j;
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLubyte *p, *tmpImage, *stencil;
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint overlapping;
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!rb) {
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* no readbuffer - OK */
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ctx->DrawBuffer == ctx->ReadBuffer) {
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      overlapping = GL_FALSE;
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Determine if copy should be bottom-to-top or top-to-bottom */
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!overlapping && srcy < desty) {
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* top-down  max-to-min */
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sy = srcy + height - 1;
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dy = desty + height - 1;
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      stepy = -1;
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* bottom-up  min-to-max */
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sy = srcy;
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dy = desty;
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      stepy = 1;
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (overlapping) {
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLint ssy = sy;
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tmpImage = (GLubyte *) malloc(width * height * sizeof(GLubyte));
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!tmpImage) {
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return;
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      p = tmpImage;
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (j = 0; j < height; j++, ssy += stepy) {
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _swrast_read_stencil_span( ctx, rb, width, srcx, ssy, p );
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p += width;
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      p = tmpImage;
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tmpImage = NULL;  /* silence compiler warning */
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      p = NULL;
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   stencil = (GLubyte *) malloc(width * sizeof(GLubyte));
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!stencil) {
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels()");
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      goto end;
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Get stencil values */
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (overlapping) {
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         memcpy(stencil, p, width * sizeof(GLubyte));
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p += width;
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _swrast_read_stencil_span( ctx, rb, width, srcx, sy, stencil );
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_apply_stencil_transfer_ops(ctx, width, stencil);
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Write stencil values */
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (zoom) {
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _swrast_write_zoomed_stencil_span(ctx, destx, desty, width,
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                           destx, dy, stencil);
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _swrast_write_stencil_span( ctx, width, destx, dy, stencil );
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   free(stencil);
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgend:
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (overlapping)
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      free(tmpImage);
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Try to do a fast 1:1 blit with memcpy.
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \return GL_TRUE if successful, GL_FALSE otherwise.
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgGLboolean
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgswrast_fast_copy_pixels(struct gl_context *ctx,
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			GLint srcX, GLint srcY, GLsizei width, GLsizei height,
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			GLint dstX, GLint dstY, GLenum type)
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_framebuffer *srcFb = ctx->ReadBuffer;
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_framebuffer *dstFb = ctx->DrawBuffer;
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_renderbuffer *srcRb, *dstRb;
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint row;
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLuint pixelBytes, widthInBytes;
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLubyte *srcMap, *dstMap;
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLint srcRowStride, dstRowStride;
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (type == GL_COLOR) {
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (dstFb->_NumColorDrawBuffers != 1)
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_FALSE;
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      srcRb = srcFb->_ColorReadBuffer;
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dstRb = dstFb->_ColorDrawBuffers[0];
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else if (type == GL_STENCIL) {
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      srcRb = srcFb->Attachment[BUFFER_STENCIL].Renderbuffer;
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dstRb = dstFb->Attachment[BUFFER_STENCIL].Renderbuffer;
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else if (type == GL_DEPTH) {
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ASSERT(type == GL_DEPTH_STENCIL_EXT);
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* XXX correct? */
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* src and dst renderbuffers must be same format */
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!srcRb || !dstRb || srcRb->Format != dstRb->Format) {
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return GL_FALSE;
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (type == GL_STENCIL || type == GL_DEPTH_COMPONENT) {
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* can't handle packed depth+stencil here */
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (_mesa_is_format_packed_depth_stencil(srcRb->Format) ||
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          _mesa_is_format_packed_depth_stencil(dstRb->Format))
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_FALSE;
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else if (type == GL_DEPTH_STENCIL) {
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* can't handle separate depth/stencil buffers */
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (srcRb != srcFb->Attachment[BUFFER_STENCIL].Renderbuffer ||
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          dstRb != dstFb->Attachment[BUFFER_STENCIL].Renderbuffer)
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_FALSE;
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* clipping not supported */
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (srcX < 0 || srcX + width > (GLint) srcFb->Width ||
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       srcY < 0 || srcY + height > (GLint) srcFb->Height ||
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       dstX < dstFb->_Xmin || dstX + width > dstFb->_Xmax ||
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       dstY < dstFb->_Ymin || dstY + height > dstFb->_Ymax) {
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return GL_FALSE;
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   pixelBytes = _mesa_get_format_bytes(srcRb->Format);
504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   widthInBytes = width * pixelBytes;
505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (srcRb == dstRb) {
507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* map whole buffer for read/write */
508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* XXX we could be clever and just map the union region of the
509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * source and dest rects.
510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLubyte *map;
512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLint rowStride;
513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Driver.MapRenderbuffer(ctx, srcRb, 0, 0,
515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  srcRb->Width, srcRb->Height,
516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  &map, &rowStride);
518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!map) {
519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_TRUE; /* don't retry with slow path */
521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      srcMap = map + srcY * rowStride + srcX * pixelBytes;
524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dstMap = map + dstY * rowStride + dstX * pixelBytes;
525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* this handles overlapping copies */
527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (srcY < dstY) {
528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* copy in reverse (top->down) order */
529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         srcMap += rowStride * (height - 1);
530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         dstMap += rowStride * (height - 1);
531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         srcRowStride = -rowStride;
532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         dstRowStride = -rowStride;
533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* copy in normal (bottom->up) order */
536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         srcRowStride = rowStride;
537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         dstRowStride = rowStride;
538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* different src/dst buffers */
542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Driver.MapRenderbuffer(ctx, srcRb, srcX, srcY,
543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  width, height,
544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  GL_MAP_READ_BIT, &srcMap, &srcRowStride);
545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!srcMap) {
546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_TRUE; /* don't retry with slow path */
548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Driver.MapRenderbuffer(ctx, dstRb, dstX, dstY,
550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  width, height,
551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!dstMap) {
553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ctx->Driver.UnmapRenderbuffer(ctx, srcRb);
554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return GL_TRUE; /* don't retry with slow path */
556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (row = 0; row < height; row++) {
560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* memmove() in case of overlap */
561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      memmove(dstMap, srcMap, widthInBytes);
562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dstMap += dstRowStride;
563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      srcMap += srcRowStride;
564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ctx->Driver.UnmapRenderbuffer(ctx, srcRb);
567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (dstRb != srcRb) {
568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Driver.UnmapRenderbuffer(ctx, dstRb);
569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return GL_TRUE;
572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Find/map the renderbuffer that we'll be reading from.
577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The swrast_render_start() function only maps the drawing buffers,
578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * not the read buffer.
579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct gl_renderbuffer *
581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmap_readbuffer(struct gl_context *ctx, GLenum type)
582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_framebuffer *fb = ctx->ReadBuffer;
584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_renderbuffer *rb;
585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct swrast_renderbuffer *srb;
586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (type) {
588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_COLOR:
589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      rb = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer;
590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_DEPTH:
592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_DEPTH_STENCIL:
593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_STENCIL:
596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   srb = swrast_renderbuffer(rb);
603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!srb || srb->Map) {
605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* no buffer, or buffer is mapped already, we're done */
606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ctx->Driver.MapRenderbuffer(ctx, rb,
610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               0, 0, rb->Width, rb->Height,
611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               GL_MAP_READ_BIT,
612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               &srb->Map, &srb->RowStride);
613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return rb;
615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Do software-based glCopyPixels.
620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * By time we get here, all parameters will have been error-checked.
621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_swrast_CopyPixels( struct gl_context *ctx,
624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    GLint srcx, GLint srcy, GLsizei width, GLsizei height,
625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    GLint destx, GLint desty, GLenum type )
626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   SWcontext *swrast = SWRAST_CONTEXT(ctx);
628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_renderbuffer *rb;
629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!_mesa_check_conditional_render(ctx))
631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return; /* don't copy */
632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (swrast->NewState)
634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _swrast_validate_derived( ctx );
635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!(SWRAST_CONTEXT(ctx)->_RasterMask != 0x0 ||
637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ctx->Pixel.ZoomX != 1.0F ||
638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ctx->Pixel.ZoomY != 1.0F ||
639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ctx->_ImageTransferState) &&
640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       swrast_fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty,
641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       type)) {
642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* all done */
643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   swrast_render_start(ctx);
647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   rb = map_readbuffer(ctx, type);
648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (type) {
650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_COLOR:
651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty );
652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_DEPTH:
654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_STENCIL:
657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case GL_DEPTH_STENCIL_EXT:
660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Copy buffers separately (if the fast copy path wasn't taken) */
661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      copy_depth_pixels(ctx, srcx, srcy, width, height, destx, desty);
662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      copy_stencil_pixels(ctx, srcx, srcy, width, height, destx, desty);
663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_problem(ctx, "unexpected type in _swrast_CopyPixels");
666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   swrast_render_finish(ctx);
669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (rb) {
671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Driver.UnmapRenderbuffer(ctx, rb);
673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      srb->Map = NULL;
674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
676