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