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      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
426edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul/**
427edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul * Bilinear interpolation of two source rows.  floating point pixels.
428edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul */
429edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paulstatic void
430edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paulresample_linear_row_float(GLint srcWidth, GLint dstWidth,
431edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                          const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
432edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                          GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
433edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul{
434edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   const GLfloat (*srcColor0)[4] = (const GLfloat (*)[4]) srcBuffer0;
435edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   const GLfloat (*srcColor1)[4] = (const GLfloat (*)[4]) srcBuffer1;
436edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLfloat (*dstColor)[4] = (GLfloat (*)[4]) dstBuffer;
437edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   const GLfloat dstWidthF = (GLfloat) dstWidth;
438edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLint dstCol;
439edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
440edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   for (dstCol = 0; dstCol < dstWidth; dstCol++) {
441edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF;
442edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      GLint srcCol0 = IFLOOR(srcCol);
443edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      GLint srcCol1 = srcCol0 + 1;
444edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
445edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      GLfloat red, green, blue, alpha;
446edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
447edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      ASSERT(srcCol0 >= 0);
448edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      ASSERT(srcCol0 < srcWidth);
449edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      ASSERT(srcCol1 <= srcWidth);
450edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
451edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      if (srcCol1 == srcWidth) {
452edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         /* last column fudge */
453edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         srcCol1--;
454edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         colWeight = 0.0;
455edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
456edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
457edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      if (flip) {
458edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         srcCol0 = srcWidth - 1 - srcCol0;
459edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         srcCol1 = srcWidth - 1 - srcCol1;
460edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
461edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
462edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      red = lerp_2d(colWeight, rowWeight,
463edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
464edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
465edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      green = lerp_2d(colWeight, rowWeight,
466edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
467edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
468edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      blue = lerp_2d(colWeight, rowWeight,
469edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
470edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
471edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      alpha = lerp_2d(colWeight, rowWeight,
472edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
473edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
474edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
475edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstColor[dstCol][RCOMP] = red;
476edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstColor[dstCol][GCOMP] = green;
477edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstColor[dstCol][BCOMP] = blue;
478edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstColor[dstCol][ACOMP] = alpha;
479edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   }
480edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul}
481edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
482edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
483c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
484c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
485edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul * Bilinear filtered blit (color only, non-integer values).
486c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
487c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void
488f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergblit_linear(struct gl_context *ctx,
489c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
490c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
491c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
492c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer;
493ff73c783cc47361ff0dd819c82d067b4b85870ddBrian   struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
494c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
495c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcWidth = ABS(srcX1 - srcX0);
496c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstWidth = ABS(dstX1 - dstX0);
497c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcHeight = ABS(srcY1 - srcY0);
498c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstHeight = ABS(dstY1 - dstY0);
499c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLfloat dstHeightF = (GLfloat) dstHeight;
500c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
501c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcXpos = MIN2(srcX0, srcX1);
502c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcYpos = MIN2(srcY0, srcY1);
503c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstXpos = MIN2(dstX0, dstX1);
504c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstYpos = MIN2(dstY0, dstY1);
505c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
506c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
507c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
508c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
509c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstRow;
510c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
511c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint pixelSize;
512c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *srcBuffer0, *srcBuffer1;
513c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint srcBufferY0 = -1, srcBufferY1 = -1;
514c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *dstBuffer;
515c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
516edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   gl_format readFormat = _mesa_get_srgb_format_linear(readRb->Format);
517edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   gl_format drawFormat = _mesa_get_srgb_format_linear(drawRb->Format);
518edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLuint bpp = _mesa_get_format_bytes(readFormat);
519edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
520edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLenum pixelType;
521edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
522edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLubyte *srcMap, *dstMap;
523edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLint srcRowStride, dstRowStride;
524edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
525edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
526edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   /* Determine datatype for resampling */
527edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   if (_mesa_get_format_max_bits(readFormat) == 8 &&
528edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul       _mesa_get_format_datatype(readFormat) == GL_UNSIGNED_NORMALIZED) {
529edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      pixelType = GL_UNSIGNED_BYTE;
530c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLubyte);
531edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   }
532edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   else {
533edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      pixelType = GL_FLOAT;
534c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLfloat);
535c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
536c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
537c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* Allocate the src/dst row buffers.
538c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul    * Keep two adjacent src rows around for bilinear sampling.
539c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul    */
54032f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   srcBuffer0 = malloc(pixelSize * srcWidth);
541c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!srcBuffer0) {
542c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
543c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
544c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
54532f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   srcBuffer1 = malloc(pixelSize * srcWidth);
546c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!srcBuffer1) {
54732f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg      free(srcBuffer0);
548c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
549c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
550c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
55132f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   dstBuffer = malloc(pixelSize * dstWidth);
552c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!dstBuffer) {
55332f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg      free(srcBuffer0);
55432f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg      free(srcBuffer1);
555c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
556c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
557c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
558c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
559edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   /*
560edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul    * Map src / dst renderbuffers
561edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul    */
562edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   if (readRb == drawRb) {
563edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      /* map whole buffer for read/write */
564edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      ctx->Driver.MapRenderbuffer(ctx, readRb,
565edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                                  0, 0, readRb->Width, readRb->Height,
566edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                                  GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
567edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                                  &srcMap, &srcRowStride);
568edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      if (!srcMap) {
569431b458f24f05db612e276e12528ce0e62707b65Vinson Lee         free(srcBuffer0);
570431b458f24f05db612e276e12528ce0e62707b65Vinson Lee         free(srcBuffer1);
571431b458f24f05db612e276e12528ce0e62707b65Vinson Lee         free(dstBuffer);
572edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
573edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         return;
574edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
575edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
576edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstMap = srcMap;
577edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstRowStride = srcRowStride;
578edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   }
579edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   else {
580edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      /* different src/dst buffers */
581edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      /* XXX with a bit of work we could just map the regions to be
582edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul       * read/written instead of the whole buffers.
583edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul       */
584edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      ctx->Driver.MapRenderbuffer(ctx, readRb,
585edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul				  0, 0, readRb->Width, readRb->Height,
586edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                                  GL_MAP_READ_BIT, &srcMap, &srcRowStride);
587edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      if (!srcMap) {
588431b458f24f05db612e276e12528ce0e62707b65Vinson Lee         free(srcBuffer0);
589431b458f24f05db612e276e12528ce0e62707b65Vinson Lee         free(srcBuffer1);
590431b458f24f05db612e276e12528ce0e62707b65Vinson Lee         free(dstBuffer);
591edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
592edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         return;
593edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
594edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      ctx->Driver.MapRenderbuffer(ctx, drawRb,
595edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                                  0, 0, drawRb->Width, drawRb->Height,
596edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                                  GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
597edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      if (!dstMap) {
598edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         ctx->Driver.UnmapRenderbuffer(ctx, readRb);
599431b458f24f05db612e276e12528ce0e62707b65Vinson Lee         free(srcBuffer0);
600431b458f24f05db612e276e12528ce0e62707b65Vinson Lee         free(srcBuffer1);
601431b458f24f05db612e276e12528ce0e62707b65Vinson Lee         free(dstBuffer);
602edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
603edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         return;
604edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
605edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   }
606edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
607c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
608c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      const GLint dstY = dstYpos + dstRow;
609c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;
610c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcRow0 = IFLOOR(srcRow);
611c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcRow1 = srcRow0 + 1;
612c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
613c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
614c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcRow >= 0);
615c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcRow < srcHeight);
616c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
617c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (srcRow1 == srcHeight) {
618c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* last row fudge */
619c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcRow1 = srcRow0;
620c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         rowWeight = 0.0;
621c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
622c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
623c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (invertY) {
624c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcRow0 = srcHeight - 1 - srcRow0;
625c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcRow1 = srcHeight - 1 - srcRow1;
626c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
627c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
628c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      srcY0 = srcYpos + srcRow0;
629c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      srcY1 = srcYpos + srcRow1;
630c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
631c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      /* get the two source rows */
632c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
633c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* use same source row buffers again */
634c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
635c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      else if (srcY0 == srcBufferY1) {
636c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* move buffer1 into buffer0 by swapping pointers */
637c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         GLvoid *tmp = srcBuffer0;
638c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBuffer0 = srcBuffer1;
639c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBuffer1 = tmp;
640c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* get y1 row */
641edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         {
642edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            GLubyte *src = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
643edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            if (pixelType == GL_UNSIGNED_BYTE) {
644edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul               _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
645edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                                           src, srcBuffer1);
646edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            }
647edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            else {
648edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul               _mesa_unpack_rgba_row(readFormat, srcWidth,
649edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                                     src, srcBuffer1);
650edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            }
651edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         }
652c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBufferY0 = srcY0;
653c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBufferY1 = srcY1;
654c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
655c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      else {
656c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* get both new rows */
657edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         {
658edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            GLubyte *src0 = srcMap + srcY0 * srcRowStride + srcXpos * bpp;
659edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            GLubyte *src1 = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
660edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            if (pixelType == GL_UNSIGNED_BYTE) {
661edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul               _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
662edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                                           src0, srcBuffer0);
663edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul               _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
664edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                                           src1, srcBuffer1);
665edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            }
666edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            else {
667edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul               _mesa_unpack_rgba_row(readFormat, srcWidth, src0, srcBuffer0);
668edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul               _mesa_unpack_rgba_row(readFormat, srcWidth, src1, srcBuffer1);
669edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            }
670edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         }
671c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBufferY0 = srcY0;
672c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBufferY1 = srcY1;
673c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
674c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
675edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      if (pixelType == GL_UNSIGNED_BYTE) {
676c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
677c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                                dstBuffer, invertX, rowWeight);
678c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
679c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      else {
680edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         resample_linear_row_float(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
681edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                                   dstBuffer, invertX, rowWeight);
682c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
683c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
684c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      /* store pixel row in destination */
685edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      {
686edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         GLubyte *dst = dstMap + dstY * dstRowStride + dstXpos * bpp;
687edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         if (pixelType == GL_UNSIGNED_BYTE) {
688edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            _mesa_pack_ubyte_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
689edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         }
690edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         else {
691edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            _mesa_pack_float_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
692edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         }
693edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
694c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
695c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
69632f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(srcBuffer0);
69732f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(srcBuffer1);
69832f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(dstBuffer);
699edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
700edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   ctx->Driver.UnmapRenderbuffer(ctx, readRb);
701edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   if (drawRb != readRb) {
702edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
703edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   }
704c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
705c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
706edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
707edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
708c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
7091eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Software fallback for glBlitFramebufferEXT().
7101eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul */
7111eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paulvoid
712f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_swrast_BlitFramebuffer(struct gl_context *ctx,
713c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
714c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
715c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLbitfield mask, GLenum filter)
7161eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul{
717b15334035177fbb031f000583ef7cb31f68b248cBrian Paul   static const GLbitfield buffers[3] = {
718c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_COLOR_BUFFER_BIT,
719c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_DEPTH_BUFFER_BIT,
720c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_STENCIL_BUFFER_BIT
721c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   };
722fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   static const GLenum buffer_enums[3] = {
723fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      GL_COLOR,
724fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      GL_DEPTH,
725fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      GL_STENCIL,
726fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   };
727c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint i;
728c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
729727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
730727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul                        &dstX0, &dstY0, &dstX1, &dstY1)) {
731c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
732c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
733c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
73422e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul   if (SWRAST_CONTEXT(ctx)->NewState)
73522e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul      _swrast_validate_derived(ctx);
73622e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul
737fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   /* First, try covering whatever buffers possible using the fast 1:1 copy
738fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt    * path.
739fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt    */
740c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (srcX1 - srcX0 == dstX1 - dstX0 &&
741c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcY1 - srcY0 == dstY1 - dstY0 &&
742c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcX0 < srcX1 &&
743c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcY0 < srcY1 &&
744c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       dstX0 < dstX1 &&
745c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       dstY0 < dstY1) {
746c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      for (i = 0; i < 3; i++) {
747c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         if (mask & buffers[i]) {
748fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	    if (swrast_fast_copy_pixels(ctx,
749fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt					srcX0, srcY0,
750fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt					srcX1 - srcX0, srcY1 - srcY0,
751fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt					dstX0, dstY0,
752fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt					buffer_enums[i])) {
753fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	       mask &= ~buffers[i];
754fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	    }
755fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 }
756c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
757fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt
758fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      if (!mask)
759fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 return;
760c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
761fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt
762fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   if (filter == GL_NEAREST) {
763fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      for (i = 0; i < 3; i++) {
764fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 if (mask & buffers[i]) {
765fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	    blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
766fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt			 dstX0, dstY0, dstX1, dstY1, buffers[i]);
767fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 }
768c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
769fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   }
770fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   else {
771fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      ASSERT(filter == GL_LINEAR);
772fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
773fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
774fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt		     dstX0, dstY0, dstX1, dstY1);
775c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
776c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
777c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
7781eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul}
779