s_blit.c revision 3786a3e644d0770e1247f24c6379388513728174
11eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul/*
21eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Mesa 3-D graphics library
31eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Version:  6.5
41eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul *
51eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
61eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul *
71eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Permission is hereby granted, free of charge, to any person obtaining a
81eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * copy of this software and associated documentation files (the "Software"),
91eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * to deal in the Software without restriction, including without limitation
101eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * the rights to use, copy, modify, merge, publish, distribute, sublicense,
111eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * and/or sell copies of the Software, and to permit persons to whom the
121eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Software is furnished to do so, subject to the following conditions:
131eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul *
141eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * The above copyright notice and this permission notice shall be included
151eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * in all copies or substantial portions of the Software.
161eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul *
171eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
181eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
191eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
201eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
211eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
221eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
231eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul */
241eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul
251eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul
26bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/glheader.h"
27ab26682eb4db0dbe160b13f1e320ec9164c3afc5Brian Paul#include "main/condrender.h"
28727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul#include "main/image.h"
29bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/macros.h"
303786a3e644d0770e1247f24c6379388513728174Eric Anholt#include "main/format_unpack.h"
313786a3e644d0770e1247f24c6379388513728174Eric Anholt#include "main/format_pack.h"
321eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul#include "s_context.h"
331eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul
341eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul
35c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul#define ABS(X)   ((X) < 0 ? -(X) : (X))
36c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
37c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
38c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
39c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Generate a row resampler function for GL_NEAREST mode.
40c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
41c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul#define RESAMPLE(NAME, PIXELTYPE, SIZE)			\
42c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void						\
43c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulNAME(GLint srcWidth, GLint dstWidth,			\
44c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul     const GLvoid *srcBuffer, GLvoid *dstBuffer,	\
45c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul     GLboolean flip)					\
46c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{							\
47c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\
48c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   PIXELTYPE *dst = (PIXELTYPE *) dstBuffer;		\
49c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstCol;					\
50c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul							\
51c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (flip) {						\
52c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\
53c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\
54c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         ASSERT(srcCol >= 0);				\
55c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         ASSERT(srcCol < srcWidth);			\
56c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol = srcWidth - 1 - srcCol; /* flip */	\
57c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         if (SIZE == 1) {				\
58c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol] = src[srcCol];			\
59c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
60c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         else if (SIZE == 2) {				\
61c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*2+0] = src[srcCol*2+0];		\
62c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*2+1] = src[srcCol*2+1];		\
63c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
64c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         else if (SIZE == 4) {				\
65c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+0] = src[srcCol*4+0];		\
66c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+1] = src[srcCol*4+1];		\
67c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+2] = src[srcCol*4+2];		\
68c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+3] = src[srcCol*4+3];		\
69c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
70c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }							\
71c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }							\
72c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   else {						\
73c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\
74c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\
75c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         ASSERT(srcCol >= 0);				\
76c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         ASSERT(srcCol < srcWidth);			\
77c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         if (SIZE == 1) {				\
78c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol] = src[srcCol];			\
79c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
80c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         else if (SIZE == 2) {				\
81c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*2+0] = src[srcCol*2+0];		\
82c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*2+1] = src[srcCol*2+1];		\
83c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
84c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         else if (SIZE == 4) {				\
85c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+0] = src[srcCol*4+0];		\
86c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+1] = src[srcCol*4+1];		\
87c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+2] = src[srcCol*4+2];		\
88c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+3] = src[srcCol*4+3];		\
89c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
90c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }							\
91c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }							\
92c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
93c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
94c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
95c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Resamplers for 1, 2, 4, 8 and 16-byte pixels.
96c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
97c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_1, GLubyte, 1)
98c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_2, GLushort, 1)
99c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_4, GLuint, 1)
100c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_8, GLuint, 2)
101c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_16, GLuint, 4)
102c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
103c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
104c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
105c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Blit color, depth or stencil with GL_NEAREST filtering.
106c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
107c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void
108f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergblit_nearest(struct gl_context *ctx,
109c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul             GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
110c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul             GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
111b15334035177fbb031f000583ef7cb31f68b248cBrian Paul             GLbitfield buffer)
112c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
113c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   struct gl_renderbuffer *readRb, *drawRb;
114c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
115c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcWidth = ABS(srcX1 - srcX0);
116c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstWidth = ABS(dstX1 - dstX0);
117c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcHeight = ABS(srcY1 - srcY0);
118c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstHeight = ABS(dstY1 - dstY0);
119c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
120c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcXpos = MIN2(srcX0, srcX1);
121c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcYpos = MIN2(srcY0, srcY1);
122c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstXpos = MIN2(dstX0, dstX1);
123c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstYpos = MIN2(dstY0, dstY1);
124c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
125c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
126c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
1273786a3e644d0770e1247f24c6379388513728174Eric Anholt   enum mode {
1283786a3e644d0770e1247f24c6379388513728174Eric Anholt      DIRECT,
1293786a3e644d0770e1247f24c6379388513728174Eric Anholt      UNPACK_RGBA_FLOAT,
1303786a3e644d0770e1247f24c6379388513728174Eric Anholt      UNPACK_Z_FLOAT,
1313786a3e644d0770e1247f24c6379388513728174Eric Anholt      UNPACK_Z_INT,
1323786a3e644d0770e1247f24c6379388513728174Eric Anholt      UNPACK_S,
1333786a3e644d0770e1247f24c6379388513728174Eric Anholt   } mode;
1343786a3e644d0770e1247f24c6379388513728174Eric Anholt   GLubyte *srcMap, *dstMap;
1353786a3e644d0770e1247f24c6379388513728174Eric Anholt   GLint srcRowStride, dstRowStride;
136c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstRow;
137c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
1383786a3e644d0770e1247f24c6379388513728174Eric Anholt   GLint pixelSize;
139c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *srcBuffer, *dstBuffer;
140c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint prevY = -1;
141c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
142c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   typedef void (*resample_func)(GLint srcWidth, GLint dstWidth,
143c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                                 const GLvoid *srcBuffer, GLvoid *dstBuffer,
144c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                                 GLboolean flip);
145c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   resample_func resampleRow;
146c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
147c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   switch (buffer) {
148c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_COLOR_BUFFER_BIT:
149c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      readRb = ctx->ReadBuffer->_ColorReadBuffer;
150ff73c783cc47361ff0dd819c82d067b4b85870ddBrian Paul      drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
1513786a3e644d0770e1247f24c6379388513728174Eric Anholt
1523786a3e644d0770e1247f24c6379388513728174Eric Anholt      if (readRb->Format == drawRb->Format) {
1533786a3e644d0770e1247f24c6379388513728174Eric Anholt	 mode = DIRECT;
1543786a3e644d0770e1247f24c6379388513728174Eric Anholt	 pixelSize = _mesa_get_format_bytes(readRb->Format);
1553786a3e644d0770e1247f24c6379388513728174Eric Anholt      } else {
1563786a3e644d0770e1247f24c6379388513728174Eric Anholt	 mode = UNPACK_RGBA_FLOAT;
1573786a3e644d0770e1247f24c6379388513728174Eric Anholt	 pixelSize = 16;
1583786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
1593786a3e644d0770e1247f24c6379388513728174Eric Anholt
160c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
161c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_DEPTH_BUFFER_BIT:
1623786a3e644d0770e1247f24c6379388513728174Eric Anholt      readRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1633786a3e644d0770e1247f24c6379388513728174Eric Anholt      drawRb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1643786a3e644d0770e1247f24c6379388513728174Eric Anholt
1653786a3e644d0770e1247f24c6379388513728174Eric Anholt      /* Note that for depth/stencil, the formats of src/dst must match.  By
1663786a3e644d0770e1247f24c6379388513728174Eric Anholt       * using the core helpers for pack/unpack, we avoid needing to handle
1673786a3e644d0770e1247f24c6379388513728174Eric Anholt       * masking for things like DEPTH copies of Z24S8.
1683786a3e644d0770e1247f24c6379388513728174Eric Anholt       */
1693786a3e644d0770e1247f24c6379388513728174Eric Anholt      if (readRb->Format == MESA_FORMAT_Z32_FLOAT ||
1703786a3e644d0770e1247f24c6379388513728174Eric Anholt	  readRb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
1713786a3e644d0770e1247f24c6379388513728174Eric Anholt	 mode = UNPACK_Z_FLOAT;
1723786a3e644d0770e1247f24c6379388513728174Eric Anholt      } else {
1733786a3e644d0770e1247f24c6379388513728174Eric Anholt	 mode = UNPACK_Z_INT;
1743786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
1753786a3e644d0770e1247f24c6379388513728174Eric Anholt      pixelSize = 4;
176c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
177c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_STENCIL_BUFFER_BIT:
1783786a3e644d0770e1247f24c6379388513728174Eric Anholt      readRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
1793786a3e644d0770e1247f24c6379388513728174Eric Anholt      drawRb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
1803786a3e644d0770e1247f24c6379388513728174Eric Anholt      mode = UNPACK_S;
1813786a3e644d0770e1247f24c6379388513728174Eric Anholt      pixelSize = 1;
182c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
183c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   default:
184c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_problem(ctx, "unexpected buffer in blit_nearest()");
185c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
186c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
187c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
188c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* choose row resampler */
189c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   switch (pixelSize) {
190c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case 1:
191c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      resampleRow = resample_row_1;
192c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
193c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case 2:
194c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      resampleRow = resample_row_2;
195c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
196c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case 4:
197c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      resampleRow = resample_row_4;
198c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
199c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case 8:
200c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      resampleRow = resample_row_8;
201c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
202c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case 16:
203c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      resampleRow = resample_row_16;
204c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
205c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   default:
206c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
207c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    pixelSize);
208c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
209c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
210c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
2113786a3e644d0770e1247f24c6379388513728174Eric Anholt   if (readRb == drawRb) {
2123786a3e644d0770e1247f24c6379388513728174Eric Anholt      /* map whole buffer for read/write */
2133786a3e644d0770e1247f24c6379388513728174Eric Anholt      /* XXX we could be clever and just map the union region of the
2143786a3e644d0770e1247f24c6379388513728174Eric Anholt       * source and dest rects.
2153786a3e644d0770e1247f24c6379388513728174Eric Anholt       */
2163786a3e644d0770e1247f24c6379388513728174Eric Anholt      GLubyte *map;
2173786a3e644d0770e1247f24c6379388513728174Eric Anholt      GLint rowStride;
2183786a3e644d0770e1247f24c6379388513728174Eric Anholt      GLint formatSize = _mesa_get_format_bytes(readRb->Format);
2193786a3e644d0770e1247f24c6379388513728174Eric Anholt
2203786a3e644d0770e1247f24c6379388513728174Eric Anholt      ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0,
2213786a3e644d0770e1247f24c6379388513728174Eric Anholt                                  readRb->Width, readRb->Height,
2223786a3e644d0770e1247f24c6379388513728174Eric Anholt                                  GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
2233786a3e644d0770e1247f24c6379388513728174Eric Anholt                                  &map, &rowStride);
2243786a3e644d0770e1247f24c6379388513728174Eric Anholt      if (!map) {
2253786a3e644d0770e1247f24c6379388513728174Eric Anholt         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
2263786a3e644d0770e1247f24c6379388513728174Eric Anholt         return;
2273786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
2283786a3e644d0770e1247f24c6379388513728174Eric Anholt
2293786a3e644d0770e1247f24c6379388513728174Eric Anholt      srcMap = map + srcYpos * rowStride + srcXpos * formatSize;
2303786a3e644d0770e1247f24c6379388513728174Eric Anholt      dstMap = map + dstYpos * rowStride + dstXpos * formatSize;
2313786a3e644d0770e1247f24c6379388513728174Eric Anholt
2323786a3e644d0770e1247f24c6379388513728174Eric Anholt      /* this handles overlapping copies */
2333786a3e644d0770e1247f24c6379388513728174Eric Anholt      if (srcY0 < dstY0) {
2343786a3e644d0770e1247f24c6379388513728174Eric Anholt         /* copy in reverse (top->down) order */
2353786a3e644d0770e1247f24c6379388513728174Eric Anholt         srcMap += rowStride * (readRb->Height - 1);
2363786a3e644d0770e1247f24c6379388513728174Eric Anholt         dstMap += rowStride * (readRb->Height - 1);
2373786a3e644d0770e1247f24c6379388513728174Eric Anholt         srcRowStride = -rowStride;
2383786a3e644d0770e1247f24c6379388513728174Eric Anholt         dstRowStride = -rowStride;
2393786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
2403786a3e644d0770e1247f24c6379388513728174Eric Anholt      else {
2413786a3e644d0770e1247f24c6379388513728174Eric Anholt         /* copy in normal (bottom->up) order */
2423786a3e644d0770e1247f24c6379388513728174Eric Anholt         srcRowStride = rowStride;
2433786a3e644d0770e1247f24c6379388513728174Eric Anholt         dstRowStride = rowStride;
2443786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
2453786a3e644d0770e1247f24c6379388513728174Eric Anholt   }
2463786a3e644d0770e1247f24c6379388513728174Eric Anholt   else {
2473786a3e644d0770e1247f24c6379388513728174Eric Anholt      /* different src/dst buffers */
2483786a3e644d0770e1247f24c6379388513728174Eric Anholt      ctx->Driver.MapRenderbuffer(ctx, readRb,
2493786a3e644d0770e1247f24c6379388513728174Eric Anholt				  srcXpos, srcYpos,
2503786a3e644d0770e1247f24c6379388513728174Eric Anholt                                  srcWidth, srcHeight,
2513786a3e644d0770e1247f24c6379388513728174Eric Anholt                                  GL_MAP_READ_BIT, &srcMap, &srcRowStride);
2523786a3e644d0770e1247f24c6379388513728174Eric Anholt      if (!srcMap) {
2533786a3e644d0770e1247f24c6379388513728174Eric Anholt         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
2543786a3e644d0770e1247f24c6379388513728174Eric Anholt         return;
2553786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
2563786a3e644d0770e1247f24c6379388513728174Eric Anholt      ctx->Driver.MapRenderbuffer(ctx, drawRb,
2573786a3e644d0770e1247f24c6379388513728174Eric Anholt				  dstXpos, dstYpos,
2583786a3e644d0770e1247f24c6379388513728174Eric Anholt                                  dstWidth, dstHeight,
2593786a3e644d0770e1247f24c6379388513728174Eric Anholt                                  GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
2603786a3e644d0770e1247f24c6379388513728174Eric Anholt      if (!dstMap) {
2613786a3e644d0770e1247f24c6379388513728174Eric Anholt         ctx->Driver.UnmapRenderbuffer(ctx, readRb);
2623786a3e644d0770e1247f24c6379388513728174Eric Anholt         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
2633786a3e644d0770e1247f24c6379388513728174Eric Anholt         return;
2643786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
2653786a3e644d0770e1247f24c6379388513728174Eric Anholt   }
2663786a3e644d0770e1247f24c6379388513728174Eric Anholt
267c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* allocate the src/dst row buffers */
26832f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   srcBuffer = malloc(pixelSize * srcWidth);
269c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!srcBuffer) {
270c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
271c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
272c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
27332f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   dstBuffer = malloc(pixelSize * dstWidth);
274c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!dstBuffer) {
27532f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg      free(srcBuffer);
276c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
277c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
278c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
279c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
280c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
281c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcRow = (dstRow * srcHeight) / dstHeight;
2823786a3e644d0770e1247f24c6379388513728174Eric Anholt      GLubyte *dstRowStart = dstMap + dstRowStride * dstRow;
283c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
284c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcRow >= 0);
285c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcRow < srcHeight);
286c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
287c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (invertY) {
288c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcRow = srcHeight - 1 - srcRow;
289c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
290c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
291c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      /* get pixel row from source and resample to match dest width */
2923786a3e644d0770e1247f24c6379388513728174Eric Anholt      if (prevY != srcRow) {
2933786a3e644d0770e1247f24c6379388513728174Eric Anholt	 GLubyte *srcRowStart = srcMap + srcRowStride * srcRow;
2943786a3e644d0770e1247f24c6379388513728174Eric Anholt
2953786a3e644d0770e1247f24c6379388513728174Eric Anholt	 switch (mode) {
2963786a3e644d0770e1247f24c6379388513728174Eric Anholt	 case DIRECT:
2973786a3e644d0770e1247f24c6379388513728174Eric Anholt	    memcpy(srcBuffer, srcRowStart, pixelSize * srcWidth);
2983786a3e644d0770e1247f24c6379388513728174Eric Anholt	    break;
2993786a3e644d0770e1247f24c6379388513728174Eric Anholt	 case UNPACK_RGBA_FLOAT:
3003786a3e644d0770e1247f24c6379388513728174Eric Anholt	    _mesa_unpack_rgba_row(readRb->Format, srcWidth, srcRowStart,
3013786a3e644d0770e1247f24c6379388513728174Eric Anholt				  srcBuffer);
3023786a3e644d0770e1247f24c6379388513728174Eric Anholt	    break;
3033786a3e644d0770e1247f24c6379388513728174Eric Anholt	 case UNPACK_Z_FLOAT:
3043786a3e644d0770e1247f24c6379388513728174Eric Anholt	    _mesa_unpack_float_z_row(readRb->Format, srcWidth, srcRowStart,
3053786a3e644d0770e1247f24c6379388513728174Eric Anholt				     srcBuffer);
3063786a3e644d0770e1247f24c6379388513728174Eric Anholt	    break;
3073786a3e644d0770e1247f24c6379388513728174Eric Anholt	 case UNPACK_Z_INT:
3083786a3e644d0770e1247f24c6379388513728174Eric Anholt	    _mesa_unpack_uint_z_row(readRb->Format, srcWidth, srcRowStart,
3093786a3e644d0770e1247f24c6379388513728174Eric Anholt				    srcBuffer);
3103786a3e644d0770e1247f24c6379388513728174Eric Anholt	    break;
3113786a3e644d0770e1247f24c6379388513728174Eric Anholt	 case UNPACK_S:
3123786a3e644d0770e1247f24c6379388513728174Eric Anholt	    _mesa_unpack_ubyte_stencil_row(readRb->Format, srcWidth,
3133786a3e644d0770e1247f24c6379388513728174Eric Anholt					   srcRowStart, srcBuffer);
3143786a3e644d0770e1247f24c6379388513728174Eric Anholt	    break;
3153786a3e644d0770e1247f24c6379388513728174Eric Anholt	 }
3163786a3e644d0770e1247f24c6379388513728174Eric Anholt
317c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
3183786a3e644d0770e1247f24c6379388513728174Eric Anholt         prevY = srcRow;
319c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
320c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
321c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      /* store pixel row in destination */
3223786a3e644d0770e1247f24c6379388513728174Eric Anholt      switch (mode) {
3233786a3e644d0770e1247f24c6379388513728174Eric Anholt      case DIRECT:
3243786a3e644d0770e1247f24c6379388513728174Eric Anholt	 memcpy(dstRowStart, dstBuffer, pixelSize * srcWidth);
3253786a3e644d0770e1247f24c6379388513728174Eric Anholt	 break;
3263786a3e644d0770e1247f24c6379388513728174Eric Anholt      case UNPACK_RGBA_FLOAT:
3273786a3e644d0770e1247f24c6379388513728174Eric Anholt	 _mesa_pack_float_rgba_row(drawRb->Format, dstWidth, dstBuffer,
3283786a3e644d0770e1247f24c6379388513728174Eric Anholt				   dstRowStart);
3293786a3e644d0770e1247f24c6379388513728174Eric Anholt	 break;
3303786a3e644d0770e1247f24c6379388513728174Eric Anholt      case UNPACK_Z_FLOAT:
3313786a3e644d0770e1247f24c6379388513728174Eric Anholt	 _mesa_pack_float_z_row(drawRb->Format, dstWidth, dstBuffer,
3323786a3e644d0770e1247f24c6379388513728174Eric Anholt				dstRowStart);
3333786a3e644d0770e1247f24c6379388513728174Eric Anholt	 break;
3343786a3e644d0770e1247f24c6379388513728174Eric Anholt      case UNPACK_Z_INT:
3353786a3e644d0770e1247f24c6379388513728174Eric Anholt	 _mesa_pack_uint_z_row(drawRb->Format, dstWidth, dstBuffer,
3363786a3e644d0770e1247f24c6379388513728174Eric Anholt			       dstRowStart);
3373786a3e644d0770e1247f24c6379388513728174Eric Anholt	 break;
3383786a3e644d0770e1247f24c6379388513728174Eric Anholt      case UNPACK_S:
3393786a3e644d0770e1247f24c6379388513728174Eric Anholt	 _mesa_pack_ubyte_stencil_row(drawRb->Format, dstWidth, dstBuffer,
3403786a3e644d0770e1247f24c6379388513728174Eric Anholt				      dstRowStart);
3413786a3e644d0770e1247f24c6379388513728174Eric Anholt	 break;
3423786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
343c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
344c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
34532f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(srcBuffer);
34632f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(dstBuffer);
3473786a3e644d0770e1247f24c6379388513728174Eric Anholt
3483786a3e644d0770e1247f24c6379388513728174Eric Anholt   ctx->Driver.UnmapRenderbuffer(ctx, readRb);
3493786a3e644d0770e1247f24c6379388513728174Eric Anholt   if (drawRb != readRb) {
3503786a3e644d0770e1247f24c6379388513728174Eric Anholt      ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
3513786a3e644d0770e1247f24c6379388513728174Eric Anholt   }
352c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
353c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
354c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
355c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
356c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul#define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) )
357c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
3589520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLfloat
359c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paullerp_2d(GLfloat a, GLfloat b,
360c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul        GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
361c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
362c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLfloat temp0 = LERP(a, v00, v10);
363c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLfloat temp1 = LERP(a, v01, v11);
364c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   return LERP(b, temp0, temp1);
365c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
366c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
367c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
368c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
369c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Bilinear interpolation of two source rows.
370c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * GLubyte pixels.
371c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
372c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void
373c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulresample_linear_row_ub(GLint srcWidth, GLint dstWidth,
374c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                       const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
375c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                       GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
376c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
377c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0;
378c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1;
379c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer;
380c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLfloat dstWidthF = (GLfloat) dstWidth;
381c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstCol;
382c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
383c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   for (dstCol = 0; dstCol < dstWidth; dstCol++) {
384c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF;
385c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcCol0 = IFLOOR(srcCol);
386c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcCol1 = srcCol0 + 1;
387c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
388c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLfloat red, green, blue, alpha;
389c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
390c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcCol0 >= 0);
391c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcCol0 < srcWidth);
392c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcCol1 <= srcWidth);
393c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
394c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (srcCol1 == srcWidth) {
395c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* last column fudge */
396c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol1--;
397c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         colWeight = 0.0;
398c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
399c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
400c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (flip) {
401c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol0 = srcWidth - 1 - srcCol0;
402c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol1 = srcWidth - 1 - srcCol1;
403c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
404c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
405c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      red = lerp_2d(colWeight, rowWeight,
406c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
407c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
408c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      green = lerp_2d(colWeight, rowWeight,
409c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
410c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
411c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      blue = lerp_2d(colWeight, rowWeight,
412c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
413c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
414c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      alpha = lerp_2d(colWeight, rowWeight,
415c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
416c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
417c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
418c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][RCOMP] = IFLOOR(red);
419c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][GCOMP] = IFLOOR(green);
420c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][BCOMP] = IFLOOR(blue);
421c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][ACOMP] = IFLOOR(alpha);
422c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
423c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
424c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
425c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
426c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
427c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
428c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Bilinear filtered blit (color only).
429c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
430c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void
431f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergblit_linear(struct gl_context *ctx,
432c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
433c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
434c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
435c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer;
436ff73c783cc47361ff0dd819c82d067b4b85870ddBrian Paul   struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
437c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
438c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcWidth = ABS(srcX1 - srcX0);
439c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstWidth = ABS(dstX1 - dstX0);
440c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcHeight = ABS(srcY1 - srcY0);
441c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstHeight = ABS(dstY1 - dstY0);
442c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLfloat dstHeightF = (GLfloat) dstHeight;
443c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
444c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcXpos = MIN2(srcX0, srcX1);
445c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcYpos = MIN2(srcY0, srcY1);
446c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstXpos = MIN2(dstX0, dstX1);
447c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstYpos = MIN2(dstY0, dstY1);
448c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
449c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
450c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
451c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
452c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstRow;
453c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
454c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint pixelSize;
455c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *srcBuffer0, *srcBuffer1;
456c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint srcBufferY0 = -1, srcBufferY1 = -1;
457c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *dstBuffer;
458c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
459c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   switch (readRb->DataType) {
460c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_UNSIGNED_BYTE:
461c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLubyte);
462c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
463c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_UNSIGNED_SHORT:
464c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLushort);
465c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
466c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_UNSIGNED_INT:
467c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLuint);
468c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
469c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_FLOAT:
470c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLfloat);
471c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
472c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   default:
473c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
474c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    readRb->DataType);
475c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
476c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
477c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
478c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* Allocate the src/dst row buffers.
479c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul    * Keep two adjacent src rows around for bilinear sampling.
480c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul    */
48132f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   srcBuffer0 = malloc(pixelSize * srcWidth);
482c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!srcBuffer0) {
483c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
484c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
485c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
48632f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   srcBuffer1 = malloc(pixelSize * srcWidth);
487c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!srcBuffer1) {
48832f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg      free(srcBuffer0);
489c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
490c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
491c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
49232f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   dstBuffer = malloc(pixelSize * dstWidth);
493c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!dstBuffer) {
49432f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg      free(srcBuffer0);
49532f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg      free(srcBuffer1);
496c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
497c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
498c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
499c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
500c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
501c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      const GLint dstY = dstYpos + dstRow;
502c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;
503c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcRow0 = IFLOOR(srcRow);
504c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcRow1 = srcRow0 + 1;
505c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
506c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
507c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcRow >= 0);
508c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcRow < srcHeight);
509c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
510c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (srcRow1 == srcHeight) {
511c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* last row fudge */
512c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcRow1 = srcRow0;
513c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         rowWeight = 0.0;
514c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
515c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
516c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (invertY) {
517c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcRow0 = srcHeight - 1 - srcRow0;
518c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcRow1 = srcHeight - 1 - srcRow1;
519c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
520c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
521c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      srcY0 = srcYpos + srcRow0;
522c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      srcY1 = srcYpos + srcRow1;
523c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
524c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      /* get the two source rows */
525c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
526c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* use same source row buffers again */
527c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
528c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      else if (srcY0 == srcBufferY1) {
529c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* move buffer1 into buffer0 by swapping pointers */
530c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         GLvoid *tmp = srcBuffer0;
531c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBuffer0 = srcBuffer1;
532c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBuffer1 = tmp;
533c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* get y1 row */
534c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
535c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBufferY0 = srcY0;
536c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBufferY1 = srcY1;
537c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
538c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      else {
539c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* get both new rows */
540c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY0, srcBuffer0);
541c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
542c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBufferY0 = srcY0;
543c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBufferY1 = srcY1;
544c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
545c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
546c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (readRb->DataType == GL_UNSIGNED_BYTE) {
547c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
548c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                                dstBuffer, invertX, rowWeight);
549c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
550c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      else {
551c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         _mesa_problem(ctx, "Unsupported color channel type in sw blit");
552c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         break;
553c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
554c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
555c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      /* store pixel row in destination */
556c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
557c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
558c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
55932f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(srcBuffer0);
56032f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(srcBuffer1);
56132f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(dstBuffer);
562c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
563c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
564c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
5651eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Software fallback for glBlitFramebufferEXT().
5661eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul */
5671eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paulvoid
568f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_swrast_BlitFramebuffer(struct gl_context *ctx,
569c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
570c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
571c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLbitfield mask, GLenum filter)
5721eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul{
573b15334035177fbb031f000583ef7cb31f68b248cBrian Paul   static const GLbitfield buffers[3] = {
574c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_COLOR_BUFFER_BIT,
575c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_DEPTH_BUFFER_BIT,
576c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_STENCIL_BUFFER_BIT
577c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   };
578fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   static const GLenum buffer_enums[3] = {
579fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      GL_COLOR,
580fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      GL_DEPTH,
581fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      GL_STENCIL,
582fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   };
583c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint i;
584c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
585727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
586727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul                        &dstX0, &dstY0, &dstX1, &dstY1)) {
587c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
588c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
589c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
59022e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul   if (SWRAST_CONTEXT(ctx)->NewState)
59122e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul      _swrast_validate_derived(ctx);
59222e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul
593fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   /* First, try covering whatever buffers possible using the fast 1:1 copy
594fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt    * path.
595fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt    */
596c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (srcX1 - srcX0 == dstX1 - dstX0 &&
597c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcY1 - srcY0 == dstY1 - dstY0 &&
598c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcX0 < srcX1 &&
599c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcY0 < srcY1 &&
600c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       dstX0 < dstX1 &&
601c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       dstY0 < dstY1) {
602c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      for (i = 0; i < 3; i++) {
603c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         if (mask & buffers[i]) {
604fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	    if (swrast_fast_copy_pixels(ctx,
605fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt					srcX0, srcY0,
606fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt					srcX1 - srcX0, srcY1 - srcY0,
607fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt					dstX0, dstY0,
608fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt					buffer_enums[i])) {
609fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	       mask &= ~buffers[i];
610fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	    }
611fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 }
612c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
613fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt
614fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      if (!mask)
615fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 return;
616c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
617fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt
618fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   if (filter == GL_NEAREST) {
619fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      for (i = 0; i < 3; i++) {
620fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 if (mask & buffers[i]) {
621fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	    blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
622fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt			 dstX0, dstY0, dstX1, dstY1, buffers[i]);
623fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 }
624c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
625fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   }
626fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   else {
627fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      ASSERT(filter == GL_LINEAR);
628fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
6293786a3e644d0770e1247f24c6379388513728174Eric Anholt	 swrast_render_start(ctx);
630fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
631fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt		     dstX0, dstY0, dstX1, dstY1);
6323786a3e644d0770e1247f24c6379388513728174Eric Anholt	 swrast_render_finish(ctx);
633c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
634c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
635c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
6361eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul}
637