s_blit.c revision 025f03f3b70989d27a20fea42763e3ccac946aa4
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{
11335aefe922660ed6e8fbad082757ae759acd711ddBrian Paul   struct gl_renderbuffer *readRb, *drawRb = NULL;
11435aefe922660ed6e8fbad082757ae759acd711ddBrian Paul   struct gl_renderbuffer_attachment *readAtt = NULL, *drawAtt = NULL;
115bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   struct gl_framebuffer *readFb = ctx->ReadBuffer;
116bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   struct gl_framebuffer *drawFb = ctx->DrawBuffer;
11757ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul   GLuint numDrawBuffers = 0;
118bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   GLuint i;
119c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
120c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcWidth = ABS(srcX1 - srcX0);
121c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstWidth = ABS(dstX1 - dstX0);
122c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcHeight = ABS(srcY1 - srcY0);
123c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstHeight = ABS(dstY1 - dstY0);
124c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
125c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcXpos = MIN2(srcX0, srcX1);
126c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcYpos = MIN2(srcY0, srcY1);
127c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstXpos = MIN2(dstX0, dstX1);
128c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstYpos = MIN2(dstY0, dstY1);
129c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
130c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
131c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
1323786a3e644d0770e1247f24c6379388513728174Eric Anholt   enum mode {
1333786a3e644d0770e1247f24c6379388513728174Eric Anholt      DIRECT,
1343786a3e644d0770e1247f24c6379388513728174Eric Anholt      UNPACK_RGBA_FLOAT,
1353786a3e644d0770e1247f24c6379388513728174Eric Anholt      UNPACK_Z_FLOAT,
1363786a3e644d0770e1247f24c6379388513728174Eric Anholt      UNPACK_Z_INT,
1373786a3e644d0770e1247f24c6379388513728174Eric Anholt      UNPACK_S,
13835aefe922660ed6e8fbad082757ae759acd711ddBrian Paul   } mode = DIRECT;
1393786a3e644d0770e1247f24c6379388513728174Eric Anholt   GLubyte *srcMap, *dstMap;
1403786a3e644d0770e1247f24c6379388513728174Eric Anholt   GLint srcRowStride, dstRowStride;
141c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstRow;
142c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
14335aefe922660ed6e8fbad082757ae759acd711ddBrian Paul   GLint pixelSize = 0;
144c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *srcBuffer, *dstBuffer;
145c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint prevY = -1;
146c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
147c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   typedef void (*resample_func)(GLint srcWidth, GLint dstWidth,
148c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                                 const GLvoid *srcBuffer, GLvoid *dstBuffer,
149c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                                 GLboolean flip);
150c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   resample_func resampleRow;
151c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
152c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   switch (buffer) {
153c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_COLOR_BUFFER_BIT:
154bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      readAtt = &readFb->Attachment[readFb->_ColorReadBufferIndex];
155bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      readRb = readFb->_ColorReadBuffer;
15657ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      numDrawBuffers = drawFb->_NumColorDrawBuffers;
157c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
158c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_DEPTH_BUFFER_BIT:
159bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      readAtt = &readFb->Attachment[BUFFER_DEPTH];
160bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      drawAtt = &drawFb->Attachment[BUFFER_DEPTH];
161bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      readRb = readAtt->Renderbuffer;
162bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      drawRb = drawAtt->Renderbuffer;
16357ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      numDrawBuffers = 1;
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:
178bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      readAtt = &readFb->Attachment[BUFFER_STENCIL];
179bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      drawAtt = &drawFb->Attachment[BUFFER_STENCIL];
180bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      readRb = readAtt->Renderbuffer;
181bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      drawRb = drawAtt->Renderbuffer;
18257ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      numDrawBuffers = 1;
1833786a3e644d0770e1247f24c6379388513728174Eric Anholt      mode = UNPACK_S;
1843786a3e644d0770e1247f24c6379388513728174Eric Anholt      pixelSize = 1;
185c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
186c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   default:
187c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_problem(ctx, "unexpected buffer in blit_nearest()");
188c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
189c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
190c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
191025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   /* allocate the src/dst row buffers */
192025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   srcBuffer = malloc(MAX_PIXEL_BYTES * srcWidth);
193025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   dstBuffer = malloc(MAX_PIXEL_BYTES * dstWidth);
194025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   if (!srcBuffer || !dstBuffer)
195025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick      goto fail_no_memory;
196025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick
197bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   /* Blit to all the draw buffers */
19857ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul   for (i = 0; i < numDrawBuffers; i++) {
199bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      if (buffer == GL_COLOR_BUFFER_BIT) {
200bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         int idx = drawFb->_ColorDrawBufferIndexes[i];
201bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (idx == -1)
202bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            continue;
203bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         drawAtt = &drawFb->Attachment[idx];
204bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         drawRb = drawAtt->Renderbuffer;
205bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
20657ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul         if (!drawRb)
20757ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul            continue;
20857ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul
209bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (readRb->Format == drawRb->Format) {
210bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            mode = DIRECT;
211bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            pixelSize = _mesa_get_format_bytes(readRb->Format);
212bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         } else {
213bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            mode = UNPACK_RGBA_FLOAT;
214bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            pixelSize = 16;
215bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
2163786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
2173786a3e644d0770e1247f24c6379388513728174Eric Anholt
218728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      /* choose row resampler */
219728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      switch (pixelSize) {
220728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      case 1:
221728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         resampleRow = resample_row_1;
222728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         break;
223728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      case 2:
224728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         resampleRow = resample_row_2;
225728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         break;
226728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      case 4:
227728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         resampleRow = resample_row_4;
228728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         break;
229728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      case 8:
230728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         resampleRow = resample_row_8;
231728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         break;
232728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      case 16:
233728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         resampleRow = resample_row_16;
234728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         break;
235728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      default:
236728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
237728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul                       pixelSize);
238025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick         goto fail;
239728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      }
240728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul
241bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      if ((readRb == drawRb) ||
242bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat          (readAtt->Texture && drawAtt->Texture &&
243bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat           (readAtt->Texture == drawAtt->Texture))) {
244bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* map whole buffer for read/write */
245bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* XXX we could be clever and just map the union region of the
246bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat          * source and dest rects.
247bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat          */
248bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         GLubyte *map;
249bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         GLint rowStride;
250bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         GLint formatSize = _mesa_get_format_bytes(readRb->Format);
251bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
252bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0,
253bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     readRb->Width, readRb->Height,
254bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
255bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     &map, &rowStride);
256bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (!map) {
257025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick            goto fail_no_memory;
258bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
259bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
260bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         srcMap = map + srcYpos * rowStride + srcXpos * formatSize;
261bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         dstMap = map + dstYpos * rowStride + dstXpos * formatSize;
2623786a3e644d0770e1247f24c6379388513728174Eric Anholt
263bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* this handles overlapping copies */
264bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (srcY0 < dstY0) {
265bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* copy in reverse (top->down) order */
266bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcMap += rowStride * (readRb->Height - 1);
267bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            dstMap += rowStride * (readRb->Height - 1);
268bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcRowStride = -rowStride;
269bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            dstRowStride = -rowStride;
270bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
271bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         else {
272bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* copy in normal (bottom->up) order */
273bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcRowStride = rowStride;
274bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            dstRowStride = rowStride;
275bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
2763786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
2773786a3e644d0770e1247f24c6379388513728174Eric Anholt      else {
278bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* different src/dst buffers */
279bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.MapRenderbuffer(ctx, readRb,
280bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     srcXpos, srcYpos,
281bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     srcWidth, srcHeight,
282bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     GL_MAP_READ_BIT, &srcMap, &srcRowStride);
283bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (!srcMap) {
284025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick            goto fail_no_memory;
285bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
286bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.MapRenderbuffer(ctx, drawRb,
287bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     dstXpos, dstYpos,
288bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     dstWidth, dstHeight,
289bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
290bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (!dstMap) {
291bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            ctx->Driver.UnmapRenderbuffer(ctx, readRb);
292025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick            goto fail_no_memory;
293bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
2943786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
295bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
296bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      for (dstRow = 0; dstRow < dstHeight; dstRow++) {
297547a418888c455a3f5158c147a155292f398ea34Brian Paul         GLfloat srcRowF = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F;
298547a418888c455a3f5158c147a155292f398ea34Brian Paul         GLint srcRow = IROUND(srcRowF);
299bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         GLubyte *dstRowStart = dstMap + dstRowStride * dstRow;
300c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
301bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ASSERT(srcRow >= 0);
302bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ASSERT(srcRow < srcHeight);
303c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
304bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (invertY) {
305bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcRow = srcHeight - 1 - srcRow;
306bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
307c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
308bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* get pixel row from source and resample to match dest width */
309bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (prevY != srcRow) {
310bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            GLubyte *srcRowStart = srcMap + srcRowStride * srcRow;
311bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
312bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            switch (mode) {
313bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            case DIRECT:
314bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               memcpy(srcBuffer, srcRowStart, pixelSize * srcWidth);
315bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               break;
316bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            case UNPACK_RGBA_FLOAT:
317bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               _mesa_unpack_rgba_row(readRb->Format, srcWidth, srcRowStart,
318bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     srcBuffer);
319bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               break;
320bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            case UNPACK_Z_FLOAT:
321bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               _mesa_unpack_float_z_row(readRb->Format, srcWidth, srcRowStart,
322bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                        srcBuffer);
323bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               break;
324bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            case UNPACK_Z_INT:
325bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               _mesa_unpack_uint_z_row(readRb->Format, srcWidth, srcRowStart,
326bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                       srcBuffer);
327bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               break;
328bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            case UNPACK_S:
329bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               _mesa_unpack_ubyte_stencil_row(readRb->Format, srcWidth,
330bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                              srcRowStart, srcBuffer);
331bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               break;
332bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            }
333c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
334bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
335bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            prevY = srcRow;
336bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
337c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
338bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* store pixel row in destination */
339bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         switch (mode) {
340bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         case DIRECT:
341b70b4862491121d5cc4444cea34f2f86a3aa5dedBrian Paul            memcpy(dstRowStart, dstBuffer, pixelSize * dstWidth);
342bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            break;
343bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         case UNPACK_RGBA_FLOAT:
344bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            _mesa_pack_float_rgba_row(drawRb->Format, dstWidth, dstBuffer,
345bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                      dstRowStart);
346bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            break;
347bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         case UNPACK_Z_FLOAT:
348bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            _mesa_pack_float_z_row(drawRb->Format, dstWidth, dstBuffer,
349bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                   dstRowStart);
350bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            break;
351bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         case UNPACK_Z_INT:
352bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            _mesa_pack_uint_z_row(drawRb->Format, dstWidth, dstBuffer,
353bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                  dstRowStart);
354bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            break;
355bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         case UNPACK_S:
356bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            _mesa_pack_ubyte_stencil_row(drawRb->Format, dstWidth, dstBuffer,
357bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                         dstRowStart);
358bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            break;
359bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
3603786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
361c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
362bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      ctx->Driver.UnmapRenderbuffer(ctx, readRb);
363bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      if (drawRb != readRb) {
364bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
365bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      }
3663786a3e644d0770e1247f24c6379388513728174Eric Anholt   }
367025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick
368025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanickfail:
369025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   free(srcBuffer);
370025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   free(dstBuffer);
371025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   return;
372025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick
373025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanickfail_no_memory:
374025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   free(srcBuffer);
375025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   free(dstBuffer);
376025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBuffer");
377c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
378c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
379c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
380c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
381c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul#define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) )
382c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
3839520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLfloat
384c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paullerp_2d(GLfloat a, GLfloat b,
385c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul        GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
386c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
387c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLfloat temp0 = LERP(a, v00, v10);
388c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLfloat temp1 = LERP(a, v01, v11);
389c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   return LERP(b, temp0, temp1);
390c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
391c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
392c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
393c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
394c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Bilinear interpolation of two source rows.
395c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * GLubyte pixels.
396c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
397c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void
398c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulresample_linear_row_ub(GLint srcWidth, GLint dstWidth,
399c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                       const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
400c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                       GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
401c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
402c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0;
403c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1;
404c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer;
405c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstCol;
406c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
407c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   for (dstCol = 0; dstCol < dstWidth; dstCol++) {
408547a418888c455a3f5158c147a155292f398ea34Brian Paul      const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F;
409547a418888c455a3f5158c147a155292f398ea34Brian Paul      GLint srcCol0 = MAX2(0, IFLOOR(srcCol));
410c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcCol1 = srcCol0 + 1;
411c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
412c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLfloat red, green, blue, alpha;
413c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
414c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcCol0 < srcWidth);
415c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      ASSERT(srcCol1 <= srcWidth);
416c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
417c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (srcCol1 == srcWidth) {
418c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* last column fudge */
419c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol1--;
420c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         colWeight = 0.0;
421c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
422c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
423c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (flip) {
424c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol0 = srcWidth - 1 - srcCol0;
425c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol1 = srcWidth - 1 - srcCol1;
426c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
427c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
428c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      red = lerp_2d(colWeight, rowWeight,
429c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
430c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
431c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      green = lerp_2d(colWeight, rowWeight,
432c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
433c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
434c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      blue = lerp_2d(colWeight, rowWeight,
435c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
436c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
437c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      alpha = lerp_2d(colWeight, rowWeight,
438c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
439c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
440c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
441c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][RCOMP] = IFLOOR(red);
442c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][GCOMP] = IFLOOR(green);
443c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][BCOMP] = IFLOOR(blue);
444c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][ACOMP] = IFLOOR(alpha);
445c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
446c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
447c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
448c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
449edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul/**
450edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul * Bilinear interpolation of two source rows.  floating point pixels.
451edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul */
452edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paulstatic void
453edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paulresample_linear_row_float(GLint srcWidth, GLint dstWidth,
454edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                          const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
455edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                          GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
456edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul{
457edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   const GLfloat (*srcColor0)[4] = (const GLfloat (*)[4]) srcBuffer0;
458edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   const GLfloat (*srcColor1)[4] = (const GLfloat (*)[4]) srcBuffer1;
459edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLfloat (*dstColor)[4] = (GLfloat (*)[4]) dstBuffer;
460edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLint dstCol;
461edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
462edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   for (dstCol = 0; dstCol < dstWidth; dstCol++) {
463547a418888c455a3f5158c147a155292f398ea34Brian Paul      const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F;
464547a418888c455a3f5158c147a155292f398ea34Brian Paul      GLint srcCol0 = MAX2(0, IFLOOR(srcCol));
465edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      GLint srcCol1 = srcCol0 + 1;
466edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
467edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      GLfloat red, green, blue, alpha;
468edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
469edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      ASSERT(srcCol0 < srcWidth);
470edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      ASSERT(srcCol1 <= srcWidth);
471edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
472edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      if (srcCol1 == srcWidth) {
473edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         /* last column fudge */
474edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         srcCol1--;
475edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         colWeight = 0.0;
476edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
477edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
478edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      if (flip) {
479edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         srcCol0 = srcWidth - 1 - srcCol0;
480edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         srcCol1 = srcWidth - 1 - srcCol1;
481edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
482edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
483edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      red = lerp_2d(colWeight, rowWeight,
484edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
485edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
486edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      green = lerp_2d(colWeight, rowWeight,
487edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
488edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
489edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      blue = lerp_2d(colWeight, rowWeight,
490edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
491edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
492edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      alpha = lerp_2d(colWeight, rowWeight,
493edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
494edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
495edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
496edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstColor[dstCol][RCOMP] = red;
497edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstColor[dstCol][GCOMP] = green;
498edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstColor[dstCol][BCOMP] = blue;
499edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstColor[dstCol][ACOMP] = alpha;
500edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   }
501edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul}
502edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
503edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
504c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
505c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
506edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul * Bilinear filtered blit (color only, non-integer values).
507c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
508c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void
509f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergblit_linear(struct gl_context *ctx,
510c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
511c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
512c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
513bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   struct gl_framebuffer *drawFb = ctx->DrawBuffer;
514bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   struct gl_framebuffer *readFb = ctx->ReadBuffer;
515bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   struct gl_renderbuffer *readRb = readFb->_ColorReadBuffer;
516bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   struct gl_renderbuffer_attachment *readAtt =
517bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      &readFb->Attachment[readFb->_ColorReadBufferIndex];
518c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
519c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcWidth = ABS(srcX1 - srcX0);
520c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstWidth = ABS(dstX1 - dstX0);
521c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcHeight = ABS(srcY1 - srcY0);
522c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstHeight = ABS(dstY1 - dstY0);
523c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
524c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcXpos = MIN2(srcX0, srcX1);
525c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcYpos = MIN2(srcY0, srcY1);
526c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstXpos = MIN2(dstX0, dstX1);
527c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstYpos = MIN2(dstY0, dstY1);
528c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
529c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
530c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
531c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
532c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstRow;
533c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
534c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint pixelSize;
535c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *srcBuffer0, *srcBuffer1;
536c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint srcBufferY0 = -1, srcBufferY1 = -1;
537c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *dstBuffer;
538c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
539edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   gl_format readFormat = _mesa_get_srgb_format_linear(readRb->Format);
540edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLuint bpp = _mesa_get_format_bytes(readFormat);
541edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
542edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLenum pixelType;
543edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
544edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLubyte *srcMap, *dstMap;
545edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLint srcRowStride, dstRowStride;
546bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   GLuint i;
547edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
548edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
549edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   /* Determine datatype for resampling */
550edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   if (_mesa_get_format_max_bits(readFormat) == 8 &&
551edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul       _mesa_get_format_datatype(readFormat) == GL_UNSIGNED_NORMALIZED) {
552edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      pixelType = GL_UNSIGNED_BYTE;
553c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLubyte);
554edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   }
555edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   else {
556edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      pixelType = GL_FLOAT;
557c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLfloat);
558c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
559c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
560c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* Allocate the src/dst row buffers.
561c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul    * Keep two adjacent src rows around for bilinear sampling.
562c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul    */
56332f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   srcBuffer0 = malloc(pixelSize * srcWidth);
56432f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   srcBuffer1 = malloc(pixelSize * srcWidth);
56532f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   dstBuffer = malloc(pixelSize * dstWidth);
5666758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick   if (!srcBuffer0 || !srcBuffer1 || !dstBuffer) {
5676758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick      goto fail_no_memory;
568c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
569c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
570bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
57157ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      GLint idx = drawFb->_ColorDrawBufferIndexes[i];
57257ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      struct gl_renderbuffer_attachment *drawAtt;
57357ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      struct gl_renderbuffer *drawRb;
57457ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      gl_format drawFormat;
57557ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul
576bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      if (idx == -1)
577bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         continue;
57857ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul
579bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      drawAtt = &drawFb->Attachment[idx];
580bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      drawRb = drawAtt->Renderbuffer;
58157ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      if (!drawRb)
58257ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul         continue;
58357ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul
58457ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      drawFormat = _mesa_get_srgb_format_linear(drawRb->Format);
58557ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul
586bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      /*
587bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat       * Map src / dst renderbuffers
588edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul       */
589bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      if ((readRb == drawRb) ||
590bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat          (readAtt->Texture && drawAtt->Texture &&
59157ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul           (readAtt->Texture == drawAtt->Texture))) {
592bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* map whole buffer for read/write */
593bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.MapRenderbuffer(ctx, readRb,
594bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     0, 0, readRb->Width, readRb->Height,
595bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
596bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     &srcMap, &srcRowStride);
597bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (!srcMap) {
5986758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick            goto fail_no_memory;
599bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
600bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
601bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         dstMap = srcMap;
602bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         dstRowStride = srcRowStride;
603edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
604bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      else {
605bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* different src/dst buffers */
606bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* XXX with a bit of work we could just map the regions to be
607bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat          * read/written instead of the whole buffers.
608bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat          */
609bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.MapRenderbuffer(ctx, readRb,
610bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     0, 0, readRb->Width, readRb->Height,
611bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     GL_MAP_READ_BIT, &srcMap, &srcRowStride);
612bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (!srcMap) {
6136758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick            goto fail_no_memory;
614bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
615bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.MapRenderbuffer(ctx, drawRb,
616bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     0, 0, drawRb->Width, drawRb->Height,
617bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
618bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (!dstMap) {
619bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            ctx->Driver.UnmapRenderbuffer(ctx, readRb);
6206758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick            goto fail_no_memory;
621bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
622edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
623edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
624bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      for (dstRow = 0; dstRow < dstHeight; dstRow++) {
625bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         const GLint dstY = dstYpos + dstRow;
626547a418888c455a3f5158c147a155292f398ea34Brian Paul         GLfloat srcRow = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F;
627547a418888c455a3f5158c147a155292f398ea34Brian Paul         GLint srcRow0 = MAX2(0, IFLOOR(srcRow));
628bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         GLint srcRow1 = srcRow0 + 1;
629bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
630c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
631bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (srcRow1 == srcHeight) {
632bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* last row fudge */
633bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcRow1 = srcRow0;
634bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            rowWeight = 0.0;
635bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
636c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
637bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (invertY) {
638bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcRow0 = srcHeight - 1 - srcRow0;
639bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcRow1 = srcHeight - 1 - srcRow1;
640bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
641c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
642bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         srcY0 = srcYpos + srcRow0;
643bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         srcY1 = srcYpos + srcRow1;
644c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
645bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* get the two source rows */
646bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
647bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* use same source row buffers again */
648bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
649bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         else if (srcY0 == srcBufferY1) {
650bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* move buffer1 into buffer0 by swapping pointers */
651bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            GLvoid *tmp = srcBuffer0;
652bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcBuffer0 = srcBuffer1;
653bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcBuffer1 = tmp;
654bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* get y1 row */
655bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            {
656bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               GLubyte *src = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
657bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               if (pixelType == GL_UNSIGNED_BYTE) {
658bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                  _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
659bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                              src, srcBuffer1);
660bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               }
661bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               else {
662bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                  _mesa_unpack_rgba_row(readFormat, srcWidth,
663bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                        src, srcBuffer1);
664bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               }
665edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            }
666bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcBufferY0 = srcY0;
667bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcBufferY1 = srcY1;
668bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
669bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         else {
670bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* get both new rows */
671bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            {
672bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               GLubyte *src0 = srcMap + srcY0 * srcRowStride + srcXpos * bpp;
673bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               GLubyte *src1 = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
674bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               if (pixelType == GL_UNSIGNED_BYTE) {
675bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                  _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
676bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                              src0, srcBuffer0);
677bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                  _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
678bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                              src1, srcBuffer1);
679bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               }
680bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               else {
681bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                  _mesa_unpack_rgba_row(readFormat, srcWidth, src0, srcBuffer0);
682bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                  _mesa_unpack_rgba_row(readFormat, srcWidth, src1, srcBuffer1);
683bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               }
684edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            }
685bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcBufferY0 = srcY0;
686bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcBufferY1 = srcY1;
687bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
688bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
689bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (pixelType == GL_UNSIGNED_BYTE) {
690bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
691bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                   dstBuffer, invertX, rowWeight);
692bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
693bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         else {
694bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            resample_linear_row_float(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
695bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                      dstBuffer, invertX, rowWeight);
696bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
697bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
698bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* store pixel row in destination */
699edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         {
700bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            GLubyte *dst = dstMap + dstY * dstRowStride + dstXpos * bpp;
701edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            if (pixelType == GL_UNSIGNED_BYTE) {
702bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               _mesa_pack_ubyte_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
703edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            }
704edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            else {
705bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               _mesa_pack_float_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
706edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            }
707edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         }
708c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
709c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
710bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      ctx->Driver.UnmapRenderbuffer(ctx, readRb);
711bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      if (drawRb != readRb) {
712bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
713edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
714c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
7156758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick
716a27c6e1aea1d048e0c701ca59c3c5bcf12b69d7bIan Romanick   free(srcBuffer0);
717a27c6e1aea1d048e0c701ca59c3c5bcf12b69d7bIan Romanick   free(srcBuffer1);
718a27c6e1aea1d048e0c701ca59c3c5bcf12b69d7bIan Romanick   free(dstBuffer);
719a27c6e1aea1d048e0c701ca59c3c5bcf12b69d7bIan Romanick   return;
720a27c6e1aea1d048e0c701ca59c3c5bcf12b69d7bIan Romanick
7216758498eb79287fe5d67cd5c869e9fd387f95defIan Romanickfail_no_memory:
7226758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick   free(srcBuffer0);
7236758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick   free(srcBuffer1);
7246758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick   free(dstBuffer);
7256758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick   _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
726c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
727c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
728edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
729edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
730c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
7311eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Software fallback for glBlitFramebufferEXT().
7321eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul */
7331eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paulvoid
734f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_swrast_BlitFramebuffer(struct gl_context *ctx,
735c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
736c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
737c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLbitfield mask, GLenum filter)
7381eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul{
739b15334035177fbb031f000583ef7cb31f68b248cBrian Paul   static const GLbitfield buffers[3] = {
740c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_COLOR_BUFFER_BIT,
741c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_DEPTH_BUFFER_BIT,
742c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_STENCIL_BUFFER_BIT
743c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   };
744fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   static const GLenum buffer_enums[3] = {
745fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      GL_COLOR,
746fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      GL_DEPTH,
747fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      GL_STENCIL,
748fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   };
749c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint i;
750c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
751727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
752727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul                        &dstX0, &dstY0, &dstX1, &dstY1)) {
753c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
754c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
755c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
75622e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul   if (SWRAST_CONTEXT(ctx)->NewState)
75722e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul      _swrast_validate_derived(ctx);
75822e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul
759fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   /* First, try covering whatever buffers possible using the fast 1:1 copy
760fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt    * path.
761fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt    */
762c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (srcX1 - srcX0 == dstX1 - dstX0 &&
763c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcY1 - srcY0 == dstY1 - dstY0 &&
764c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcX0 < srcX1 &&
765c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcY0 < srcY1 &&
766c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       dstX0 < dstX1 &&
767c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       dstY0 < dstY1) {
768c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      for (i = 0; i < 3; i++) {
769c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         if (mask & buffers[i]) {
770fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	    if (swrast_fast_copy_pixels(ctx,
771fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt					srcX0, srcY0,
772fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt					srcX1 - srcX0, srcY1 - srcY0,
773fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt					dstX0, dstY0,
774fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt					buffer_enums[i])) {
775fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	       mask &= ~buffers[i];
776fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	    }
777fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 }
778c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
779fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt
780fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      if (!mask)
781fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 return;
782c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
783fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt
784fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   if (filter == GL_NEAREST) {
785fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      for (i = 0; i < 3; i++) {
786fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 if (mask & buffers[i]) {
787fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	    blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
788fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt			 dstX0, dstY0, dstX1, dstY1, buffers[i]);
789fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 }
790c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
791fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   }
792fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   else {
793fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      ASSERT(filter == GL_LINEAR);
794fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
795fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt	 blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
796fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt		     dstX0, dstY0, dstX1, dstY1);
797c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
798c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
799c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
8001eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul}
801