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