s_blit.c revision 22e806f57013b2c116b5bfab228e0f28e25198f4
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"
301eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul#include "s_context.h"
311eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul
321eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul
33c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul#define ABS(X)   ((X) < 0 ? -(X) : (X))
34c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
35c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
36c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
37c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Generate a row resampler function for GL_NEAREST mode.
38c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
39c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul#define RESAMPLE(NAME, PIXELTYPE, SIZE)			\
40c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void						\
41c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulNAME(GLint srcWidth, GLint dstWidth,			\
42c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul     const GLvoid *srcBuffer, GLvoid *dstBuffer,	\
43c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul     GLboolean flip)					\
44c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{							\
45c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\
46c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   PIXELTYPE *dst = (PIXELTYPE *) dstBuffer;		\
47c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstCol;					\
48c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul							\
49c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (flip) {						\
50c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\
51c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\
52c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         ASSERT(srcCol >= 0);				\
53c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         ASSERT(srcCol < srcWidth);			\
54c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol = srcWidth - 1 - srcCol; /* flip */	\
55c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         if (SIZE == 1) {				\
56c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol] = src[srcCol];			\
57c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
58c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         else if (SIZE == 2) {				\
59c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*2+0] = src[srcCol*2+0];		\
60c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*2+1] = src[srcCol*2+1];		\
61c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
62c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         else if (SIZE == 4) {				\
63c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+0] = src[srcCol*4+0];		\
64c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+1] = src[srcCol*4+1];		\
65c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+2] = src[srcCol*4+2];		\
66c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+3] = src[srcCol*4+3];		\
67c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
68c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }							\
69c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }							\
70c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   else {						\
71c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\
72c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\
73c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         ASSERT(srcCol >= 0);				\
74c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         ASSERT(srcCol < srcWidth);			\
75c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         if (SIZE == 1) {				\
76c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol] = src[srcCol];			\
77c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
78c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         else if (SIZE == 2) {				\
79c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*2+0] = src[srcCol*2+0];		\
80c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*2+1] = src[srcCol*2+1];		\
81c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
82c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         else if (SIZE == 4) {				\
83c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+0] = src[srcCol*4+0];		\
84c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+1] = src[srcCol*4+1];		\
85c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+2] = src[srcCol*4+2];		\
86c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+3] = src[srcCol*4+3];		\
87c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
88c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }							\
89c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }							\
90c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
91c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
92c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
93c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Resamplers for 1, 2, 4, 8 and 16-byte pixels.
94c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
95c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_1, GLubyte, 1)
96c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_2, GLushort, 1)
97c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_4, GLuint, 1)
98c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_8, GLuint, 2)
99c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_16, GLuint, 4)
100c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
101c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
102c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
103c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Blit color, depth or stencil with GL_NEAREST filtering.
104c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
105c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void
106f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergblit_nearest(struct gl_context *ctx,
107c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul             GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
108c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul             GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
109b15334035177fbb031f000583ef7cb31f68b248cBrian Paul             GLbitfield buffer)
110c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
111c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   struct gl_renderbuffer *readRb, *drawRb;
112c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
113c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcWidth = ABS(srcX1 - srcX0);
114c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstWidth = ABS(dstX1 - dstX0);
115c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcHeight = ABS(srcY1 - srcY0);
116c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstHeight = ABS(dstY1 - dstY0);
117c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
118c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcXpos = MIN2(srcX0, srcX1);
119c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcYpos = MIN2(srcY0, srcY1);
120c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstXpos = MIN2(dstX0, dstX1);
121c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstYpos = MIN2(dstY0, dstY1);
122c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
123c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
124c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
125c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
126c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstRow;
127c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
128c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint comps, pixelSize;
129c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *srcBuffer, *dstBuffer;
130c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint prevY = -1;
131c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
132c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   typedef void (*resample_func)(GLint srcWidth, GLint dstWidth,
133c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                                 const GLvoid *srcBuffer, GLvoid *dstBuffer,
134c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                                 GLboolean flip);
135c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   resample_func resampleRow;
136c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
137c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   switch (buffer) {
138c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_COLOR_BUFFER_BIT:
139c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      readRb = ctx->ReadBuffer->_ColorReadBuffer;
140ff73c783cc47361ff0dd819c82d067b4b85870ddBrian Paul      drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
141c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      comps = 4;
142c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
143c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_DEPTH_BUFFER_BIT:
144c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      readRb = ctx->ReadBuffer->_DepthBuffer;
145c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      drawRb = ctx->DrawBuffer->_DepthBuffer;
146c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      comps = 1;
147c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
148c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_STENCIL_BUFFER_BIT:
149c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      readRb = ctx->ReadBuffer->_StencilBuffer;
150c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      drawRb = ctx->DrawBuffer->_StencilBuffer;
151c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      comps = 1;
152c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
153c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   default:
154c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_problem(ctx, "unexpected buffer in blit_nearest()");
155c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
156c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
157c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
158c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   switch (readRb->DataType) {
159c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_UNSIGNED_BYTE:
160c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = comps * sizeof(GLubyte);
161c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
162c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_UNSIGNED_SHORT:
163c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = comps * sizeof(GLushort);
164c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
165c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_UNSIGNED_INT:
166c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = comps * sizeof(GLuint);
167c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
168c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_FLOAT:
169c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = comps * sizeof(GLfloat);
170c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
171c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   default:
172c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
173c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    readRb->DataType);
174c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
175c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
176c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
177c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* choose row resampler */
178c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   switch (pixelSize) {
179c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case 1:
180c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      resampleRow = resample_row_1;
181c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
182c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case 2:
183c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      resampleRow = resample_row_2;
184c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
185c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case 4:
186c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      resampleRow = resample_row_4;
187c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
188c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case 8:
189c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      resampleRow = resample_row_8;
190c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
191c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case 16:
192c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      resampleRow = resample_row_16;
193c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
194c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   default:
195c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
196c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    pixelSize);
197c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
198c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
199c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
200c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* allocate the src/dst row buffers */
20132f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   srcBuffer = malloc(pixelSize * srcWidth);
202c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!srcBuffer) {
203c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
204c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
205c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
20632f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   dstBuffer = malloc(pixelSize * dstWidth);
207c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!dstBuffer) {
20832f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg      free(srcBuffer);
209c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
210c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
211c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
212c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
213c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
214c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      const GLint dstY = dstYpos + dstRow;
215c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcRow = (dstRow * srcHeight) / dstHeight;
216c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcY;
217c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
218c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcRow >= 0);
219c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcRow < srcHeight);
220c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
221c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (invertY) {
222c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcRow = srcHeight - 1 - srcRow;
223c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
224c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
225c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      srcY = srcYpos + srcRow;
226c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
227c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      /* get pixel row from source and resample to match dest width */
228c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (prevY != srcY) {
229c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY, srcBuffer);
230c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
231c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         prevY = srcY;
232c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
233c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
234c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      /* store pixel row in destination */
235c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
236c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
237c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
23832f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(srcBuffer);
23932f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(dstBuffer);
240c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
241c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
242c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
243c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
244c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul#define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) )
245c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
2469520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLfloat
247c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paullerp_2d(GLfloat a, GLfloat b,
248c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul        GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
249c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
250c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLfloat temp0 = LERP(a, v00, v10);
251c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLfloat temp1 = LERP(a, v01, v11);
252c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   return LERP(b, temp0, temp1);
253c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
254c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
255c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
256c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
257c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Bilinear interpolation of two source rows.
258c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * GLubyte pixels.
259c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
260c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void
261c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulresample_linear_row_ub(GLint srcWidth, GLint dstWidth,
262c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                       const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
263c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                       GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
264c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
265c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0;
266c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1;
267c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer;
268c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLfloat dstWidthF = (GLfloat) dstWidth;
269c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstCol;
270c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
271c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   for (dstCol = 0; dstCol < dstWidth; dstCol++) {
272c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF;
273c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcCol0 = IFLOOR(srcCol);
274c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcCol1 = srcCol0 + 1;
275c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
276c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLfloat red, green, blue, alpha;
277c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
278c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcCol0 >= 0);
279c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcCol0 < srcWidth);
280c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcCol1 <= srcWidth);
281c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
282c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (srcCol1 == srcWidth) {
283c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* last column fudge */
284c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol1--;
285c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         colWeight = 0.0;
286c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
287c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
288c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (flip) {
289c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol0 = srcWidth - 1 - srcCol0;
290c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol1 = srcWidth - 1 - srcCol1;
291c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
292c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
293c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      red = lerp_2d(colWeight, rowWeight,
294c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
295c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
296c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      green = lerp_2d(colWeight, rowWeight,
297c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
298c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
299c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      blue = lerp_2d(colWeight, rowWeight,
300c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
301c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
302c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      alpha = lerp_2d(colWeight, rowWeight,
303c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
304c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
305c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
306c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][RCOMP] = IFLOOR(red);
307c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][GCOMP] = IFLOOR(green);
308c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][BCOMP] = IFLOOR(blue);
309c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][ACOMP] = IFLOOR(alpha);
310c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
311c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
312c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
313c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
314c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
315c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
316c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Bilinear filtered blit (color only).
317c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
318c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void
319f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergblit_linear(struct gl_context *ctx,
320c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
321c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
322c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
323c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer;
324ff73c783cc47361ff0dd819c82d067b4b85870ddBrian Paul   struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
325c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
326c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcWidth = ABS(srcX1 - srcX0);
327c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstWidth = ABS(dstX1 - dstX0);
328c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcHeight = ABS(srcY1 - srcY0);
329c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstHeight = ABS(dstY1 - dstY0);
330c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLfloat dstHeightF = (GLfloat) dstHeight;
331c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
332c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcXpos = MIN2(srcX0, srcX1);
333c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcYpos = MIN2(srcY0, srcY1);
334c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstXpos = MIN2(dstX0, dstX1);
335c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstYpos = MIN2(dstY0, dstY1);
336c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
337c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
338c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
339c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
340c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstRow;
341c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
342c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint pixelSize;
343c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *srcBuffer0, *srcBuffer1;
344c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint srcBufferY0 = -1, srcBufferY1 = -1;
345c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *dstBuffer;
346c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
347c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   switch (readRb->DataType) {
348c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_UNSIGNED_BYTE:
349c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLubyte);
350c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
351c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_UNSIGNED_SHORT:
352c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLushort);
353c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
354c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_UNSIGNED_INT:
355c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLuint);
356c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
357c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_FLOAT:
358c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLfloat);
359c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
360c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   default:
361c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
362c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    readRb->DataType);
363c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
364c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
365c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
366c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* Allocate the src/dst row buffers.
367c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul    * Keep two adjacent src rows around for bilinear sampling.
368c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul    */
36932f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   srcBuffer0 = malloc(pixelSize * srcWidth);
370c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!srcBuffer0) {
371c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
372c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
373c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
37432f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   srcBuffer1 = malloc(pixelSize * srcWidth);
375c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!srcBuffer1) {
37632f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg      free(srcBuffer0);
377c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
378c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
379c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
38032f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   dstBuffer = malloc(pixelSize * dstWidth);
381c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!dstBuffer) {
38232f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg      free(srcBuffer0);
38332f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg      free(srcBuffer1);
384c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
385c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
386c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
387c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
388c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
389c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      const GLint dstY = dstYpos + dstRow;
390c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;
391c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcRow0 = IFLOOR(srcRow);
392c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcRow1 = srcRow0 + 1;
393c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
394c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
395c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcRow >= 0);
396c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcRow < srcHeight);
397c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
398c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (srcRow1 == srcHeight) {
399c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* last row fudge */
400c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcRow1 = srcRow0;
401c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         rowWeight = 0.0;
402c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
403c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
404c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (invertY) {
405c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcRow0 = srcHeight - 1 - srcRow0;
406c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcRow1 = srcHeight - 1 - srcRow1;
407c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
408c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
409c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      srcY0 = srcYpos + srcRow0;
410c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      srcY1 = srcYpos + srcRow1;
411c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
412c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      /* get the two source rows */
413c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
414c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* use same source row buffers again */
415c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
416c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      else if (srcY0 == srcBufferY1) {
417c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* move buffer1 into buffer0 by swapping pointers */
418c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         GLvoid *tmp = srcBuffer0;
419c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBuffer0 = srcBuffer1;
420c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBuffer1 = tmp;
421c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* get y1 row */
422c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
423c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBufferY0 = srcY0;
424c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBufferY1 = srcY1;
425c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
426c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      else {
427c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* get both new rows */
428c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY0, srcBuffer0);
429c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
430c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBufferY0 = srcY0;
431c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcBufferY1 = srcY1;
432c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
433c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
434c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (readRb->DataType == GL_UNSIGNED_BYTE) {
435c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
436c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                                dstBuffer, invertX, rowWeight);
437c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
438c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      else {
439c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         _mesa_problem(ctx, "Unsupported color channel type in sw blit");
440c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         break;
441c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
442c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
443c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      /* store pixel row in destination */
444c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
445c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
446c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
44732f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(srcBuffer0);
44832f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(srcBuffer1);
44932f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(dstBuffer);
450c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
451c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
452c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
453c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
454c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Simple case:  Blit color, depth or stencil with no scaling or flipping.
455c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * XXX we could easily support vertical flipping here.
456c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
457c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void
458f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsimple_blit(struct gl_context *ctx,
459c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
460c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
461b15334035177fbb031f000583ef7cb31f68b248cBrian Paul            GLbitfield buffer)
462c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
463c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   struct gl_renderbuffer *readRb, *drawRb;
464c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint width = srcX1 - srcX0;
465c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint height = srcY1 - srcY0;
466c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint row, srcY, dstY, yStep;
467c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint comps, bytesPerRow;
468c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   void *rowBuffer;
469c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
470c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* only one buffer */
471c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   ASSERT(_mesa_bitcount(buffer) == 1);
472c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* no flipping checks */
473c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   ASSERT(srcX0 < srcX1);
474c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   ASSERT(srcY0 < srcY1);
475c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   ASSERT(dstX0 < dstX1);
476c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   ASSERT(dstY0 < dstY1);
477c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* size checks */
478c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   ASSERT(srcX1 - srcX0 == dstX1 - dstX0);
479c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   ASSERT(srcY1 - srcY0 == dstY1 - dstY0);
480c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
481c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* determine if copy should be bottom-to-top or top-to-bottom */
482c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (srcY0 > dstY0) {
483c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      /* src above dst: copy bottom-to-top */
484c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      yStep = 1;
485c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      srcY = srcY0;
486c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstY = dstY0;
487c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
488c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   else {
489c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      /* src below dst: copy top-to-bottom */
490c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      yStep = -1;
491c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      srcY = srcY1 - 1;
492c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstY = dstY1 - 1;
493c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
494c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
495c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   switch (buffer) {
496c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_COLOR_BUFFER_BIT:
497c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      readRb = ctx->ReadBuffer->_ColorReadBuffer;
498ff73c783cc47361ff0dd819c82d067b4b85870ddBrian Paul      drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
499c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      comps = 4;
500c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
501c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_DEPTH_BUFFER_BIT:
502c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      readRb = ctx->ReadBuffer->_DepthBuffer;
503c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      drawRb = ctx->DrawBuffer->_DepthBuffer;
504c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      comps = 1;
505c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
506c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_STENCIL_BUFFER_BIT:
507c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      readRb = ctx->ReadBuffer->_StencilBuffer;
508c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      drawRb = ctx->DrawBuffer->_StencilBuffer;
509c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      comps = 1;
510c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
511c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   default:
512c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_problem(ctx, "unexpected buffer in simple_blit()");
513c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
514c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
515c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
516c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   ASSERT(readRb->DataType == drawRb->DataType);
517c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
518c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* compute bytes per row */
519c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   switch (readRb->DataType) {
520c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_UNSIGNED_BYTE:
521c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      bytesPerRow = comps * width * sizeof(GLubyte);
522c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
523c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_UNSIGNED_SHORT:
524c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      bytesPerRow = comps * width * sizeof(GLushort);
525c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
526c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_UNSIGNED_INT:
527c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      bytesPerRow = comps * width * sizeof(GLuint);
528c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
529c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_FLOAT:
530c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      bytesPerRow = comps * width * sizeof(GLfloat);
531c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
532c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   default:
533c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_problem(ctx, "unexpected buffer type in simple_blit");
534c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
535c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
536c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
537c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* allocate the row buffer */
53832f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   rowBuffer = malloc(bytesPerRow);
539c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (!rowBuffer) {
540c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
541c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
542c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
543c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
544c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   for (row = 0; row < height; row++) {
545c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      readRb->GetRow(ctx, readRb, width, srcX0, srcY, rowBuffer);
546c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      drawRb->PutRow(ctx, drawRb, width, dstX0, dstY, rowBuffer, NULL);
547c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      srcY += yStep;
548c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstY += yStep;
549c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
550c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
55132f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(rowBuffer);
552c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
553c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
554c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
555c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
5561eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Software fallback for glBlitFramebufferEXT().
5571eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul */
5581eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paulvoid
559f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_swrast_BlitFramebuffer(struct gl_context *ctx,
560c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
561c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
562c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLbitfield mask, GLenum filter)
5631eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul{
564b15334035177fbb031f000583ef7cb31f68b248cBrian Paul   static const GLbitfield buffers[3] = {
565c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_COLOR_BUFFER_BIT,
566c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_DEPTH_BUFFER_BIT,
567c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_STENCIL_BUFFER_BIT
568c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   };
569c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint i;
570c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
571727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
572727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul                        &dstX0, &dstY0, &dstX1, &dstY1)) {
573c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
574c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
575c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
57622e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul   if (SWRAST_CONTEXT(ctx)->NewState)
57722e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul      _swrast_validate_derived(ctx);
57822e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul
5792d5b86be25a7ccb729e746aa5e1bdd537d76df68Brian Paul   swrast_render_start(ctx);
580c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
581c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (srcX1 - srcX0 == dstX1 - dstX0 &&
582c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcY1 - srcY0 == dstY1 - dstY0 &&
583c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcX0 < srcX1 &&
584c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcY0 < srcY1 &&
585c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       dstX0 < dstX1 &&
586c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       dstY0 < dstY1) {
587c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      /* no stretching or flipping.
588c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       * filter doesn't matter.
589c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       */
590c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      for (i = 0; i < 3; i++) {
591c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         if (mask & buffers[i]) {
592c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            simple_blit(ctx, srcX0, srcY0, srcX1, srcY1,
593c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        dstX0, dstY0, dstX1, dstY1, buffers[i]);
594c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }
595c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
596c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
597c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   else {
598c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (filter == GL_NEAREST) {
599c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         for (i = 0; i < 3; i++) {
600c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            if (mask & buffers[i]) {
601c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul               blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
602c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                            dstX0, dstY0, dstX1, dstY1, buffers[i]);
603c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            }
604c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }
605c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
606c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      else {
607c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         ASSERT(filter == GL_LINEAR);
608c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
609c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
610c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        dstX0, dstY0, dstX1, dstY1);
611c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }
612c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
613c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
614c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
6152d5b86be25a7ccb729e746aa5e1bdd537d76df68Brian Paul   swrast_render_finish(ctx);
6161eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul}
617