11eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul/*
21eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Mesa 3-D graphics library
31eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul *
41eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
51eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul *
61eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Permission is hereby granted, free of charge, to any person obtaining a
71eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * copy of this software and associated documentation files (the "Software"),
81eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * to deal in the Software without restriction, including without limitation
91eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * the rights to use, copy, modify, merge, publish, distribute, sublicense,
101eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * and/or sell copies of the Software, and to permit persons to whom the
111eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Software is furnished to do so, subject to the following conditions:
121eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul *
131eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * The above copyright notice and this permission notice shall be included
141eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * in all copies or substantial portions of the Software.
151eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul *
161eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
171eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
181eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
193d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
203d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
213d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
223d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * 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"
328ed42ddd7d31b6c9c65c735ad27ca2873859129eAnuj Phogat#include "main/condrender.h"
331eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul#include "s_context.h"
341eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul
351eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul
36c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul#define ABS(X)   ((X) < 0 ? -(X) : (X))
37c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
38c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
39c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
40c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Generate a row resampler function for GL_NEAREST mode.
41c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
42c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul#define RESAMPLE(NAME, PIXELTYPE, SIZE)			\
43c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void						\
44c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulNAME(GLint srcWidth, GLint dstWidth,			\
45c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul     const GLvoid *srcBuffer, GLvoid *dstBuffer,	\
46c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul     GLboolean flip)					\
47c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{							\
48c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\
49c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   PIXELTYPE *dst = (PIXELTYPE *) dstBuffer;		\
50c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstCol;					\
51c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul							\
52c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (flip) {						\
53c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\
54c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\
55bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner         assert(srcCol >= 0);				\
56bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner         assert(srcCol < srcWidth);			\
57c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol = srcWidth - 1 - srcCol; /* flip */	\
58c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         if (SIZE == 1) {				\
59c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol] = src[srcCol];			\
60c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
61c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         else if (SIZE == 2) {				\
62c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*2+0] = src[srcCol*2+0];		\
63c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*2+1] = src[srcCol*2+1];		\
64c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
65c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         else if (SIZE == 4) {				\
66c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+0] = src[srcCol*4+0];		\
67c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+1] = src[srcCol*4+1];		\
68c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+2] = src[srcCol*4+2];		\
69c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+3] = src[srcCol*4+3];		\
70c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
71c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }							\
72c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }							\
73c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   else {						\
74c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\
75c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\
76bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner         assert(srcCol >= 0);				\
77bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner         assert(srcCol < srcWidth);			\
78c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         if (SIZE == 1) {				\
79c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol] = src[srcCol];			\
80c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
81c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         else if (SIZE == 2) {				\
82c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*2+0] = src[srcCol*2+0];		\
83c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*2+1] = src[srcCol*2+1];		\
84c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
85c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         else if (SIZE == 4) {				\
86c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+0] = src[srcCol*4+0];		\
87c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+1] = src[srcCol*4+1];		\
88c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+2] = src[srcCol*4+2];		\
89c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            dst[dstCol*4+3] = src[srcCol*4+3];		\
90c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         }						\
91c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }							\
92c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }							\
93c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
94c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
95c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
96c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Resamplers for 1, 2, 4, 8 and 16-byte pixels.
97c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
98c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_1, GLubyte, 1)
99c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_2, GLushort, 1)
100c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_4, GLuint, 1)
101c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_8, GLuint, 2)
102c241d3b06a5c996cb8415a6ada23288621c1d254Brian PaulRESAMPLE(resample_row_16, GLuint, 4)
103c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
104c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
105c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
106c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Blit color, depth or stencil with GL_NEAREST filtering.
107c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
108c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void
109f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergblit_nearest(struct gl_context *ctx,
110e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand             struct gl_framebuffer *readFb,
111e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand             struct gl_framebuffer *drawFb,
112c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul             GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
113c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul             GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
114b15334035177fbb031f000583ef7cb31f68b248cBrian Paul             GLbitfield buffer)
115c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
11635aefe922660ed6e8fbad082757ae759acd711ddBrian Paul   struct gl_renderbuffer *readRb, *drawRb = NULL;
11735aefe922660ed6e8fbad082757ae759acd711ddBrian Paul   struct gl_renderbuffer_attachment *readAtt = NULL, *drawAtt = NULL;
11857ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul   GLuint numDrawBuffers = 0;
119bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   GLuint i;
120c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
121c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcWidth = ABS(srcX1 - srcX0);
122c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstWidth = ABS(dstX1 - dstX0);
123c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcHeight = ABS(srcY1 - srcY0);
124c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstHeight = ABS(dstY1 - dstY0);
125c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
126c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcXpos = MIN2(srcX0, srcX1);
127c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcYpos = MIN2(srcY0, srcY1);
128c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstXpos = MIN2(dstX0, dstX1);
129c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstYpos = MIN2(dstY0, dstY1);
130c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
131c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
132c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
1333786a3e644d0770e1247f24c6379388513728174Eric Anholt   enum mode {
1343786a3e644d0770e1247f24c6379388513728174Eric Anholt      DIRECT,
1353786a3e644d0770e1247f24c6379388513728174Eric Anholt      UNPACK_RGBA_FLOAT,
1363786a3e644d0770e1247f24c6379388513728174Eric Anholt      UNPACK_Z_FLOAT,
1373786a3e644d0770e1247f24c6379388513728174Eric Anholt      UNPACK_Z_INT,
1383786a3e644d0770e1247f24c6379388513728174Eric Anholt      UNPACK_S,
13935aefe922660ed6e8fbad082757ae759acd711ddBrian Paul   } mode = DIRECT;
1403786a3e644d0770e1247f24c6379388513728174Eric Anholt   GLubyte *srcMap, *dstMap;
1413786a3e644d0770e1247f24c6379388513728174Eric Anholt   GLint srcRowStride, dstRowStride;
142c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstRow;
143c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
14435aefe922660ed6e8fbad082757ae759acd711ddBrian Paul   GLint pixelSize = 0;
145c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *srcBuffer, *dstBuffer;
146c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint prevY = -1;
147c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
148c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   typedef void (*resample_func)(GLint srcWidth, GLint dstWidth,
149c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                                 const GLvoid *srcBuffer, GLvoid *dstBuffer,
150c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                                 GLboolean flip);
151c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   resample_func resampleRow;
152c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
153c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   switch (buffer) {
154c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_COLOR_BUFFER_BIT:
155bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      readAtt = &readFb->Attachment[readFb->_ColorReadBufferIndex];
156bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      readRb = readFb->_ColorReadBuffer;
15757ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      numDrawBuffers = drawFb->_NumColorDrawBuffers;
158c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
159c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_DEPTH_BUFFER_BIT:
160bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      readAtt = &readFb->Attachment[BUFFER_DEPTH];
161bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      drawAtt = &drawFb->Attachment[BUFFER_DEPTH];
162bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      readRb = readAtt->Renderbuffer;
163bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      drawRb = drawAtt->Renderbuffer;
16457ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      numDrawBuffers = 1;
1653786a3e644d0770e1247f24c6379388513728174Eric Anholt
1663786a3e644d0770e1247f24c6379388513728174Eric Anholt      /* Note that for depth/stencil, the formats of src/dst must match.  By
1673786a3e644d0770e1247f24c6379388513728174Eric Anholt       * using the core helpers for pack/unpack, we avoid needing to handle
1683786a3e644d0770e1247f24c6379388513728174Eric Anholt       * masking for things like DEPTH copies of Z24S8.
1693786a3e644d0770e1247f24c6379388513728174Eric Anholt       */
17050a01d2acafb2a937e62b24258e2e777c0cd1489Mark Mueller      if (readRb->Format == MESA_FORMAT_Z_FLOAT32 ||
171eeed49f5f290793870c60b5b635b977a732a1eb4Mark Mueller	  readRb->Format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) {
1723786a3e644d0770e1247f24c6379388513728174Eric Anholt	 mode = UNPACK_Z_FLOAT;
1733786a3e644d0770e1247f24c6379388513728174Eric Anholt      } else {
1743786a3e644d0770e1247f24c6379388513728174Eric Anholt	 mode = UNPACK_Z_INT;
1753786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
1763786a3e644d0770e1247f24c6379388513728174Eric Anholt      pixelSize = 4;
177c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
178c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   case GL_STENCIL_BUFFER_BIT:
179bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      readAtt = &readFb->Attachment[BUFFER_STENCIL];
180bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      drawAtt = &drawFb->Attachment[BUFFER_STENCIL];
181bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      readRb = readAtt->Renderbuffer;
182bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      drawRb = drawAtt->Renderbuffer;
18357ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      numDrawBuffers = 1;
1843786a3e644d0770e1247f24c6379388513728174Eric Anholt      mode = UNPACK_S;
1853786a3e644d0770e1247f24c6379388513728174Eric Anholt      pixelSize = 1;
186c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      break;
187c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   default:
188c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      _mesa_problem(ctx, "unexpected buffer in blit_nearest()");
189c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
190c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
191c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
192025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   /* allocate the src/dst row buffers */
193025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   srcBuffer = malloc(MAX_PIXEL_BYTES * srcWidth);
194025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   dstBuffer = malloc(MAX_PIXEL_BYTES * dstWidth);
195025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   if (!srcBuffer || !dstBuffer)
196025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick      goto fail_no_memory;
197025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick
198bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   /* Blit to all the draw buffers */
19957ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul   for (i = 0; i < numDrawBuffers; i++) {
200bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      if (buffer == GL_COLOR_BUFFER_BIT) {
201bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         int idx = drawFb->_ColorDrawBufferIndexes[i];
202bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (idx == -1)
203bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            continue;
204bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         drawAtt = &drawFb->Attachment[idx];
205bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         drawRb = drawAtt->Renderbuffer;
206bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
20757ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul         if (!drawRb)
20857ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul            continue;
20957ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul
210bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (readRb->Format == drawRb->Format) {
211bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            mode = DIRECT;
212bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            pixelSize = _mesa_get_format_bytes(readRb->Format);
213bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         } else {
214bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            mode = UNPACK_RGBA_FLOAT;
215bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            pixelSize = 16;
216bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
2173786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
2183786a3e644d0770e1247f24c6379388513728174Eric Anholt
219728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      /* choose row resampler */
220728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      switch (pixelSize) {
221728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      case 1:
222728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         resampleRow = resample_row_1;
223728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         break;
224728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      case 2:
225728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         resampleRow = resample_row_2;
226728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         break;
227728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      case 4:
228728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         resampleRow = resample_row_4;
229728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         break;
230728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      case 8:
231728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         resampleRow = resample_row_8;
232728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         break;
233728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      case 16:
234728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         resampleRow = resample_row_16;
235728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         break;
236728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      default:
237728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul         _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
238728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul                       pixelSize);
239025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick         goto fail;
240728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul      }
241728bf86a23f6de137c0871ea87b09e75e55468a9Brian Paul
242bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      if ((readRb == drawRb) ||
243bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat          (readAtt->Texture && drawAtt->Texture &&
244bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat           (readAtt->Texture == drawAtt->Texture))) {
245bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* map whole buffer for read/write */
246bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* XXX we could be clever and just map the union region of the
247bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat          * source and dest rects.
248bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat          */
249bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         GLubyte *map;
250bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         GLint rowStride;
251bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         GLint formatSize = _mesa_get_format_bytes(readRb->Format);
252bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
253bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0,
254bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     readRb->Width, readRb->Height,
255bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
256bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     &map, &rowStride);
257bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (!map) {
258025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick            goto fail_no_memory;
259bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
260bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
261bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         srcMap = map + srcYpos * rowStride + srcXpos * formatSize;
262bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         dstMap = map + dstYpos * rowStride + dstXpos * formatSize;
2633786a3e644d0770e1247f24c6379388513728174Eric Anholt
264bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* this handles overlapping copies */
265bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (srcY0 < dstY0) {
266bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* copy in reverse (top->down) order */
267bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcMap += rowStride * (readRb->Height - 1);
268bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            dstMap += rowStride * (readRb->Height - 1);
269bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcRowStride = -rowStride;
270bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            dstRowStride = -rowStride;
271bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
272bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         else {
273bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* copy in normal (bottom->up) order */
274bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcRowStride = rowStride;
275bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            dstRowStride = rowStride;
276bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
2773786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
2783786a3e644d0770e1247f24c6379388513728174Eric Anholt      else {
279bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* different src/dst buffers */
280bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.MapRenderbuffer(ctx, readRb,
281bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     srcXpos, srcYpos,
282bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     srcWidth, srcHeight,
283bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     GL_MAP_READ_BIT, &srcMap, &srcRowStride);
284bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (!srcMap) {
285025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick            goto fail_no_memory;
286bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
287bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.MapRenderbuffer(ctx, drawRb,
288bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     dstXpos, dstYpos,
289bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     dstWidth, dstHeight,
290bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
291bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (!dstMap) {
292bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            ctx->Driver.UnmapRenderbuffer(ctx, readRb);
293025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick            goto fail_no_memory;
294bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
2953786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
296bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
297bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      for (dstRow = 0; dstRow < dstHeight; dstRow++) {
298547a418888c455a3f5158c147a155292f398ea34Brian Paul         GLfloat srcRowF = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F;
299547a418888c455a3f5158c147a155292f398ea34Brian Paul         GLint srcRow = IROUND(srcRowF);
300bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         GLubyte *dstRowStart = dstMap + dstRowStride * dstRow;
301c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
302bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner         assert(srcRow >= 0);
303bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner         assert(srcRow < srcHeight);
304c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
305bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (invertY) {
306bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcRow = srcHeight - 1 - srcRow;
307bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
308c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
309bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* get pixel row from source and resample to match dest width */
310bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (prevY != srcRow) {
311bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            GLubyte *srcRowStart = srcMap + srcRowStride * srcRow;
312bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
313bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            switch (mode) {
314bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            case DIRECT:
315bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               memcpy(srcBuffer, srcRowStart, pixelSize * srcWidth);
316bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               break;
317bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            case UNPACK_RGBA_FLOAT:
318bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               _mesa_unpack_rgba_row(readRb->Format, srcWidth, srcRowStart,
319bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     srcBuffer);
320bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               break;
321bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            case UNPACK_Z_FLOAT:
322bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               _mesa_unpack_float_z_row(readRb->Format, srcWidth, srcRowStart,
323bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                        srcBuffer);
324bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               break;
325bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            case UNPACK_Z_INT:
326bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               _mesa_unpack_uint_z_row(readRb->Format, srcWidth, srcRowStart,
327bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                       srcBuffer);
328bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               break;
329bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            case UNPACK_S:
330bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               _mesa_unpack_ubyte_stencil_row(readRb->Format, srcWidth,
331bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                              srcRowStart, srcBuffer);
332bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               break;
333bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            }
334c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
335bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
336bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            prevY = srcRow;
337bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
338c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
339bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* store pixel row in destination */
340bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         switch (mode) {
341bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         case DIRECT:
342b70b4862491121d5cc4444cea34f2f86a3aa5dedBrian Paul            memcpy(dstRowStart, dstBuffer, pixelSize * dstWidth);
343bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            break;
344bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         case UNPACK_RGBA_FLOAT:
345bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            _mesa_pack_float_rgba_row(drawRb->Format, dstWidth, dstBuffer,
346bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                      dstRowStart);
347bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            break;
348bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         case UNPACK_Z_FLOAT:
349bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            _mesa_pack_float_z_row(drawRb->Format, dstWidth, dstBuffer,
350bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                   dstRowStart);
351bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            break;
352bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         case UNPACK_Z_INT:
353bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            _mesa_pack_uint_z_row(drawRb->Format, dstWidth, dstBuffer,
354bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                  dstRowStart);
355bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            break;
356bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         case UNPACK_S:
357bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            _mesa_pack_ubyte_stencil_row(drawRb->Format, dstWidth, dstBuffer,
358bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                         dstRowStart);
359bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            break;
360bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
3613786a3e644d0770e1247f24c6379388513728174Eric Anholt      }
362c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
363bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      ctx->Driver.UnmapRenderbuffer(ctx, readRb);
364bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      if (drawRb != readRb) {
365bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
366bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      }
3673786a3e644d0770e1247f24c6379388513728174Eric Anholt   }
368025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick
369025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanickfail:
370025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   free(srcBuffer);
371025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   free(dstBuffer);
372025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   return;
373025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick
374025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanickfail_no_memory:
375025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   free(srcBuffer);
376025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   free(dstBuffer);
377025f03f3b70989d27a20fea42763e3ccac946aa4Ian Romanick   _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBuffer");
378c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
379c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
380c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
381c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
382c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul#define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) )
383c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
3849520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLfloat
385c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paullerp_2d(GLfloat a, GLfloat b,
386c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul        GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
387c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
388c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLfloat temp0 = LERP(a, v00, v10);
389c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLfloat temp1 = LERP(a, v01, v11);
390c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   return LERP(b, temp0, temp1);
391c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
392c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
393c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
394c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
395c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * Bilinear interpolation of two source rows.
396c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul * GLubyte pixels.
397c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
398c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void
399c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulresample_linear_row_ub(GLint srcWidth, GLint dstWidth,
400c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                       const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
401c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                       GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
402c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
403c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0;
404c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1;
405c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer;
406c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstCol;
407c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
408c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   for (dstCol = 0; dstCol < dstWidth; dstCol++) {
409547a418888c455a3f5158c147a155292f398ea34Brian Paul      const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F;
410547a418888c455a3f5158c147a155292f398ea34Brian Paul      GLint srcCol0 = MAX2(0, IFLOOR(srcCol));
411c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLint srcCol1 = srcCol0 + 1;
412c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
413c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GLfloat red, green, blue, alpha;
414c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
415bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(srcCol0 < srcWidth);
416bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(srcCol1 <= srcWidth);
417c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
418c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (srcCol1 == srcWidth) {
419c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         /* last column fudge */
420c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol1--;
421c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         colWeight = 0.0;
422c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
423c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
424c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      if (flip) {
425c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol0 = srcWidth - 1 - srcCol0;
426c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         srcCol1 = srcWidth - 1 - srcCol1;
427c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
428c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
429c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      red = lerp_2d(colWeight, rowWeight,
430c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
431c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
432c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      green = lerp_2d(colWeight, rowWeight,
433c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
434c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
435c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      blue = lerp_2d(colWeight, rowWeight,
436c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
437c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
438c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      alpha = lerp_2d(colWeight, rowWeight,
439c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
440c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                    srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
441c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
442c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][RCOMP] = IFLOOR(red);
443c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][GCOMP] = IFLOOR(green);
444c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][BCOMP] = IFLOOR(blue);
445c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      dstColor[dstCol][ACOMP] = IFLOOR(alpha);
446c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
447c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
448c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
449c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
450edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul/**
451edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul * Bilinear interpolation of two source rows.  floating point pixels.
452edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul */
453edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paulstatic void
454edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paulresample_linear_row_float(GLint srcWidth, GLint dstWidth,
455edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                          const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
456edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                          GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
457edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul{
458edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   const GLfloat (*srcColor0)[4] = (const GLfloat (*)[4]) srcBuffer0;
459edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   const GLfloat (*srcColor1)[4] = (const GLfloat (*)[4]) srcBuffer1;
460edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLfloat (*dstColor)[4] = (GLfloat (*)[4]) dstBuffer;
461edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLint dstCol;
462edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
463edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   for (dstCol = 0; dstCol < dstWidth; dstCol++) {
464547a418888c455a3f5158c147a155292f398ea34Brian Paul      const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F;
465547a418888c455a3f5158c147a155292f398ea34Brian Paul      GLint srcCol0 = MAX2(0, IFLOOR(srcCol));
466edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      GLint srcCol1 = srcCol0 + 1;
467edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
468edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      GLfloat red, green, blue, alpha;
469edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
470bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(srcCol0 < srcWidth);
471bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(srcCol1 <= srcWidth);
472edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
473edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      if (srcCol1 == srcWidth) {
474edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         /* last column fudge */
475edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         srcCol1--;
476edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         colWeight = 0.0;
477edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
478edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
479edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      if (flip) {
480edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         srcCol0 = srcWidth - 1 - srcCol0;
481edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         srcCol1 = srcWidth - 1 - srcCol1;
482edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
483edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
484edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      red = lerp_2d(colWeight, rowWeight,
485edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
486edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
487edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      green = lerp_2d(colWeight, rowWeight,
488edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
489edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
490edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      blue = lerp_2d(colWeight, rowWeight,
491edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
492edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
493edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      alpha = lerp_2d(colWeight, rowWeight,
494edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
495edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul                    srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
496edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
497edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstColor[dstCol][RCOMP] = red;
498edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstColor[dstCol][GCOMP] = green;
499edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstColor[dstCol][BCOMP] = blue;
500edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      dstColor[dstCol][ACOMP] = alpha;
501edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   }
502edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul}
503edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
504edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
505c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
506c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
507edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul * Bilinear filtered blit (color only, non-integer values).
508c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul */
509c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paulstatic void
510f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergblit_linear(struct gl_context *ctx,
511e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand            struct gl_framebuffer *readFb,
512e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand            struct gl_framebuffer *drawFb,
513c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
514c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
515c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul{
516bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   struct gl_renderbuffer *readRb = readFb->_ColorReadBuffer;
517bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   struct gl_renderbuffer_attachment *readAtt =
518bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      &readFb->Attachment[readFb->_ColorReadBufferIndex];
519c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
520c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcWidth = ABS(srcX1 - srcX0);
521c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstWidth = ABS(dstX1 - dstX0);
522c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcHeight = ABS(srcY1 - srcY0);
523c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstHeight = ABS(dstY1 - dstY0);
524c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
525c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcXpos = MIN2(srcX0, srcX1);
526c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint srcYpos = MIN2(srcY0, srcY1);
527c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstXpos = MIN2(dstX0, dstX1);
528c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLint dstYpos = MIN2(dstY0, dstY1);
529c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
530c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
531c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
532c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
533c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint dstRow;
534c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
535c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint pixelSize;
536c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *srcBuffer0, *srcBuffer1;
537c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint srcBufferY0 = -1, srcBufferY1 = -1;
538c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLvoid *dstBuffer;
539c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
54071fe9437169cfdafda8814aa814bb85429fb6cfcMark Mueller   mesa_format readFormat = _mesa_get_srgb_format_linear(readRb->Format);
541edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLuint bpp = _mesa_get_format_bytes(readFormat);
542edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
543edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLenum pixelType;
544edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
545edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLubyte *srcMap, *dstMap;
546edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   GLint srcRowStride, dstRowStride;
547bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   GLuint i;
548edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
549edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
550edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   /* Determine datatype for resampling */
551edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   if (_mesa_get_format_max_bits(readFormat) == 8 &&
552edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul       _mesa_get_format_datatype(readFormat) == GL_UNSIGNED_NORMALIZED) {
553edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      pixelType = GL_UNSIGNED_BYTE;
554c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLubyte);
555edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   }
556edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul   else {
557edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      pixelType = GL_FLOAT;
558c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      pixelSize = 4 * sizeof(GLfloat);
559c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
560c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
561c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   /* Allocate the src/dst row buffers.
562c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul    * Keep two adjacent src rows around for bilinear sampling.
563c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul    */
56432f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   srcBuffer0 = malloc(pixelSize * srcWidth);
56532f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   srcBuffer1 = malloc(pixelSize * srcWidth);
56632f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   dstBuffer = malloc(pixelSize * dstWidth);
5676758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick   if (!srcBuffer0 || !srcBuffer1 || !dstBuffer) {
5686758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick      goto fail_no_memory;
569c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
570c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
571bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat   for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
57257ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      GLint idx = drawFb->_ColorDrawBufferIndexes[i];
57357ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      struct gl_renderbuffer_attachment *drawAtt;
57457ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      struct gl_renderbuffer *drawRb;
57571fe9437169cfdafda8814aa814bb85429fb6cfcMark Mueller      mesa_format drawFormat;
57657ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul
577bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      if (idx == -1)
578bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         continue;
57957ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul
580bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      drawAtt = &drawFb->Attachment[idx];
581bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      drawRb = drawAtt->Renderbuffer;
58257ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      if (!drawRb)
58357ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul         continue;
58457ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul
58557ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul      drawFormat = _mesa_get_srgb_format_linear(drawRb->Format);
58657ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul
587bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      /*
588bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat       * Map src / dst renderbuffers
589edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul       */
590bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      if ((readRb == drawRb) ||
591bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat          (readAtt->Texture && drawAtt->Texture &&
59257ddf1227fffbfda52c9310f9092c036ad4558b6Brian Paul           (readAtt->Texture == drawAtt->Texture))) {
593bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* map whole buffer for read/write */
594bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.MapRenderbuffer(ctx, readRb,
595bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     0, 0, readRb->Width, readRb->Height,
596bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
597bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     &srcMap, &srcRowStride);
598bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (!srcMap) {
5996758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick            goto fail_no_memory;
600bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
601bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
602bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         dstMap = srcMap;
603bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         dstRowStride = srcRowStride;
604edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
605bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      else {
606bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* different src/dst buffers */
607bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* XXX with a bit of work we could just map the regions to be
608bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat          * read/written instead of the whole buffers.
609bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat          */
610bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.MapRenderbuffer(ctx, readRb,
611bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     0, 0, readRb->Width, readRb->Height,
612bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     GL_MAP_READ_BIT, &srcMap, &srcRowStride);
613bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (!srcMap) {
6146758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick            goto fail_no_memory;
615bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
616bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.MapRenderbuffer(ctx, drawRb,
617bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     0, 0, drawRb->Width, drawRb->Height,
618bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                     GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
619bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (!dstMap) {
620bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            ctx->Driver.UnmapRenderbuffer(ctx, readRb);
6216758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick            goto fail_no_memory;
622bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
623edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
624edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
625bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      for (dstRow = 0; dstRow < dstHeight; dstRow++) {
626bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         const GLint dstY = dstYpos + dstRow;
627547a418888c455a3f5158c147a155292f398ea34Brian Paul         GLfloat srcRow = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F;
628547a418888c455a3f5158c147a155292f398ea34Brian Paul         GLint srcRow0 = MAX2(0, IFLOOR(srcRow));
629bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         GLint srcRow1 = srcRow0 + 1;
630bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
631c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
632bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (srcRow1 == srcHeight) {
633bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* last row fudge */
634bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcRow1 = srcRow0;
635bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            rowWeight = 0.0;
636bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
637c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
638bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (invertY) {
639bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcRow0 = srcHeight - 1 - srcRow0;
640bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcRow1 = srcHeight - 1 - srcRow1;
641bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
642c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
643bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         srcY0 = srcYpos + srcRow0;
644bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         srcY1 = srcYpos + srcRow1;
645c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
646bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* get the two source rows */
647bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
648bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* use same source row buffers again */
649bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
650bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         else if (srcY0 == srcBufferY1) {
651bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* move buffer1 into buffer0 by swapping pointers */
652bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            GLvoid *tmp = srcBuffer0;
653bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcBuffer0 = srcBuffer1;
654bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcBuffer1 = tmp;
655bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* get y1 row */
656bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            {
657bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               GLubyte *src = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
658bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               if (pixelType == GL_UNSIGNED_BYTE) {
659bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                  _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
660bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                              src, srcBuffer1);
661bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               }
662bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               else {
663bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                  _mesa_unpack_rgba_row(readFormat, srcWidth,
664bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                        src, srcBuffer1);
665bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               }
666edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            }
667bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcBufferY0 = srcY0;
668bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcBufferY1 = srcY1;
669bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
670bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         else {
671bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            /* get both new rows */
672bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            {
673bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               GLubyte *src0 = srcMap + srcY0 * srcRowStride + srcXpos * bpp;
674bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               GLubyte *src1 = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
675bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               if (pixelType == GL_UNSIGNED_BYTE) {
676bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                  _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
677bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                              src0, srcBuffer0);
678bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                  _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
679bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                              src1, srcBuffer1);
680bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               }
681bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               else {
682bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                  _mesa_unpack_rgba_row(readFormat, srcWidth, src0, srcBuffer0);
683bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                  _mesa_unpack_rgba_row(readFormat, srcWidth, src1, srcBuffer1);
684bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               }
685edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            }
686bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcBufferY0 = srcY0;
687bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            srcBufferY1 = srcY1;
688bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
689bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
690bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         if (pixelType == GL_UNSIGNED_BYTE) {
691bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
692bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                   dstBuffer, invertX, rowWeight);
693bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
694bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         else {
695bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            resample_linear_row_float(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
696bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat                                      dstBuffer, invertX, rowWeight);
697bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         }
698bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat
699bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         /* store pixel row in destination */
700edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         {
701bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat            GLubyte *dst = dstMap + dstY * dstRowStride + dstXpos * bpp;
702edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            if (pixelType == GL_UNSIGNED_BYTE) {
703bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               _mesa_pack_ubyte_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
704edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            }
705edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            else {
706bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat               _mesa_pack_float_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
707edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul            }
708edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul         }
709c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
710c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
711bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      ctx->Driver.UnmapRenderbuffer(ctx, readRb);
712bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat      if (drawRb != readRb) {
713bed997dabaada5e7c8081db08f93a6f1b5932e8bAnuj Phogat         ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
714edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul      }
715c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
7166758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick
717a27c6e1aea1d048e0c701ca59c3c5bcf12b69d7bIan Romanick   free(srcBuffer0);
718a27c6e1aea1d048e0c701ca59c3c5bcf12b69d7bIan Romanick   free(srcBuffer1);
719a27c6e1aea1d048e0c701ca59c3c5bcf12b69d7bIan Romanick   free(dstBuffer);
720a27c6e1aea1d048e0c701ca59c3c5bcf12b69d7bIan Romanick   return;
721a27c6e1aea1d048e0c701ca59c3c5bcf12b69d7bIan Romanick
7226758498eb79287fe5d67cd5c869e9fd387f95defIan Romanickfail_no_memory:
7236758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick   free(srcBuffer0);
7246758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick   free(srcBuffer1);
7256758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick   free(dstBuffer);
7266758498eb79287fe5d67cd5c869e9fd387f95defIan Romanick   _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
727c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul}
728c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
729edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
730edca96547a2063c38d65a96e80fe6ad7144b5796Brian Paul
731c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul/**
7321eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul * Software fallback for glBlitFramebufferEXT().
7331eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul */
7341eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paulvoid
735f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_swrast_BlitFramebuffer(struct gl_context *ctx,
736e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand                        struct gl_framebuffer *readFb,
737e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand                        struct gl_framebuffer *drawFb,
738c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
739c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
740c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul                        GLbitfield mask, GLenum filter)
7411eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul{
742b15334035177fbb031f000583ef7cb31f68b248cBrian Paul   static const GLbitfield buffers[3] = {
743c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_COLOR_BUFFER_BIT,
744c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_DEPTH_BUFFER_BIT,
745c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      GL_STENCIL_BUFFER_BIT
746c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   };
747fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   static const GLenum buffer_enums[3] = {
748fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      GL_COLOR,
749fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      GL_DEPTH,
750fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      GL_STENCIL,
751fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   };
752c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   GLint i;
753c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
7548ed42ddd7d31b6c9c65c735ad27ca2873859129eAnuj Phogat   /* Page 679 of OpenGL 4.4 spec says:
7558ed42ddd7d31b6c9c65c735ad27ca2873859129eAnuj Phogat    *    "Added BlitFramebuffer to commands affected by conditional rendering in
7568ed42ddd7d31b6c9c65c735ad27ca2873859129eAnuj Phogat    *     section 10.10 (Bug 9562)."
7578ed42ddd7d31b6c9c65c735ad27ca2873859129eAnuj Phogat    */
7588ed42ddd7d31b6c9c65c735ad27ca2873859129eAnuj Phogat   if (!_mesa_check_conditional_render(ctx))
7598ed42ddd7d31b6c9c65c735ad27ca2873859129eAnuj Phogat      return; /* Do not blit */
7608ed42ddd7d31b6c9c65c735ad27ca2873859129eAnuj Phogat
761e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand   if (!_mesa_clip_blit(ctx, readFb, drawFb, &srcX0, &srcY0, &srcX1, &srcY1,
762727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul                        &dstX0, &dstY0, &dstX1, &dstY1)) {
763c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      return;
764c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
765c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
76622e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul   if (SWRAST_CONTEXT(ctx)->NewState)
76722e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul      _swrast_validate_derived(ctx);
76822e806f57013b2c116b5bfab228e0f28e25198f4Brian Paul
769fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   /* First, try covering whatever buffers possible using the fast 1:1 copy
770fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt    * path.
771fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt    */
772c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   if (srcX1 - srcX0 == dstX1 - dstX0 &&
773c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcY1 - srcY0 == dstY1 - dstY0 &&
774c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcX0 < srcX1 &&
775c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       srcY0 < srcY1 &&
776c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       dstX0 < dstX1 &&
777c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul       dstY0 < dstY1) {
778c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      for (i = 0; i < 3; i++) {
779c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul         if (mask & buffers[i]) {
780e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand            if (swrast_fast_copy_pixels(ctx,
781e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand                                        readFb, drawFb,
782e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand                                        srcX0, srcY0,
783e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand                                        srcX1 - srcX0, srcY1 - srcY0,
784e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand                                        dstX0, dstY0,
785e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand                                        buffer_enums[i])) {
786e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand               mask &= ~buffers[i];
787e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand            }
788e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand         }
789c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
790fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt
791fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      if (!mask)
792e9b86cb5d66867b66c6d453d7bd60bd56fe6587dLaura Ekstrand         return;
793c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
794fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt
795fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   if (filter == GL_NEAREST) {
796fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      for (i = 0; i < 3; i++) {
797e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand          if (mask & buffers[i]) {
798e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand             blit_nearest(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1,
799e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand                          dstX0, dstY0, dstX1, dstY1, buffers[i]);
800e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand          }
801c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
802fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   }
803fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt   else {
804bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(filter == GL_LINEAR);
805fb5252a3518dadd51e88e87382e6510998e9e2f4Eric Anholt      if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
806e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand         blit_linear(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1,
807e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand                     dstX0, dstY0, dstX1, dstY1);
808c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul      }
809c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul   }
810c241d3b06a5c996cb8415a6ada23288621c1d254Brian Paul
8111eca891dbe39a4aad7a6ed267ce7cd55589073feBrian Paul}
812