⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s_blit.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Mesa 3-D graphics library * Version:  6.5 * * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */#include "glheader.h"#include "macros.h"#include "s_context.h"#define ABS(X)   ((X) < 0 ? -(X) : (X))/** * Generate a row resampler function for GL_NEAREST mode. */#define RESAMPLE(NAME, PIXELTYPE, SIZE)			\static void						\NAME(GLint srcWidth, GLint dstWidth,			\     const GLvoid *srcBuffer, GLvoid *dstBuffer,	\     GLboolean flip)					\{							\   const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\   PIXELTYPE *dst = (PIXELTYPE *) dstBuffer;		\   GLint dstCol;					\							\   if (flip) {						\      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\         ASSERT(srcCol >= 0);				\         ASSERT(srcCol < srcWidth);			\         srcCol = srcWidth - 1 - srcCol; /* flip */	\         if (SIZE == 1) {				\            dst[dstCol] = src[srcCol];			\         }						\         else if (SIZE == 2) {				\            dst[dstCol*2+0] = src[srcCol*2+0];		\            dst[dstCol*2+1] = src[srcCol*2+1];		\         }						\         else if (SIZE == 4) {				\            dst[dstCol*4+0] = src[srcCol*4+0];		\            dst[dstCol*4+1] = src[srcCol*4+1];		\            dst[dstCol*4+2] = src[srcCol*4+2];		\            dst[dstCol*4+3] = src[srcCol*4+3];		\         }						\      }							\   }							\   else {						\      for (dstCol = 0; dstCol < dstWidth; dstCol++) {	\         GLint srcCol = (dstCol * srcWidth) / dstWidth;	\         ASSERT(srcCol >= 0);				\         ASSERT(srcCol < srcWidth);			\         if (SIZE == 1) {				\            dst[dstCol] = src[srcCol];			\         }						\         else if (SIZE == 2) {				\            dst[dstCol*2+0] = src[srcCol*2+0];		\            dst[dstCol*2+1] = src[srcCol*2+1];		\         }						\         else if (SIZE == 4) {				\            dst[dstCol*4+0] = src[srcCol*4+0];		\            dst[dstCol*4+1] = src[srcCol*4+1];		\            dst[dstCol*4+2] = src[srcCol*4+2];		\            dst[dstCol*4+3] = src[srcCol*4+3];		\         }						\      }							\   }							\}/** * Resamplers for 1, 2, 4, 8 and 16-byte pixels. */RESAMPLE(resample_row_1, GLubyte, 1)RESAMPLE(resample_row_2, GLushort, 1)RESAMPLE(resample_row_4, GLuint, 1)RESAMPLE(resample_row_8, GLuint, 2)RESAMPLE(resample_row_16, GLuint, 4)/** * Blit color, depth or stencil with GL_NEAREST filtering. */static voidblit_nearest(GLcontext *ctx,             GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,             GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,             GLenum buffer){   struct gl_renderbuffer *readRb, *drawRb;   const GLint srcWidth = ABS(srcX1 - srcX0);   const GLint dstWidth = ABS(dstX1 - dstX0);   const GLint srcHeight = ABS(srcY1 - srcY0);   const GLint dstHeight = ABS(dstY1 - dstY0);   const GLint srcXpos = MIN2(srcX0, srcX1);   const GLint srcYpos = MIN2(srcY0, srcY1);   const GLint dstXpos = MIN2(dstX0, dstX1);   const GLint dstYpos = MIN2(dstY0, dstY1);   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);   GLint dstRow;   GLint comps, pixelSize;   GLvoid *srcBuffer, *dstBuffer;   GLint prevY = -1;   typedef void (*resample_func)(GLint srcWidth, GLint dstWidth,                                 const GLvoid *srcBuffer, GLvoid *dstBuffer,                                 GLboolean flip);   resample_func resampleRow;   switch (buffer) {   case GL_COLOR_BUFFER_BIT:      readRb = ctx->ReadBuffer->_ColorReadBuffer;      drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];      comps = 4;      break;   case GL_DEPTH_BUFFER_BIT:      readRb = ctx->ReadBuffer->_DepthBuffer;      drawRb = ctx->DrawBuffer->_DepthBuffer;      comps = 1;      break;   case GL_STENCIL_BUFFER_BIT:      readRb = ctx->ReadBuffer->_StencilBuffer;      drawRb = ctx->DrawBuffer->_StencilBuffer;      comps = 1;      break;   default:      _mesa_problem(ctx, "unexpected buffer in blit_nearest()");      return;   }   switch (readRb->DataType) {   case GL_UNSIGNED_BYTE:      pixelSize = comps * sizeof(GLubyte);      break;   case GL_UNSIGNED_SHORT:      pixelSize = comps * sizeof(GLushort);      break;   case GL_UNSIGNED_INT:      pixelSize = comps * sizeof(GLuint);      break;   case GL_FLOAT:      pixelSize = comps * sizeof(GLfloat);      break;   default:      _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",                    readRb->DataType);      return;   }   /* choose row resampler */   switch (pixelSize) {   case 1:      resampleRow = resample_row_1;      break;   case 2:      resampleRow = resample_row_2;      break;   case 4:      resampleRow = resample_row_4;      break;   case 8:      resampleRow = resample_row_8;      break;   case 16:      resampleRow = resample_row_16;      break;   default:      _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",                    pixelSize);      return;   }   /* allocate the src/dst row buffers */   srcBuffer = _mesa_malloc(pixelSize * srcWidth);   if (!srcBuffer) {      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");      return;   }   dstBuffer = _mesa_malloc(pixelSize * dstWidth);   if (!dstBuffer) {      _mesa_free(srcBuffer);      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");      return;   }   for (dstRow = 0; dstRow < dstHeight; dstRow++) {      const GLint dstY = dstYpos + dstRow;      GLint srcRow = (dstRow * srcHeight) / dstHeight;      GLint srcY;      ASSERT(srcRow >= 0);      ASSERT(srcRow < srcHeight);      if (invertY) {         srcRow = srcHeight - 1 - srcRow;      }      srcY = srcYpos + srcRow;      /* get pixel row from source and resample to match dest width */      if (prevY != srcY) {         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY, srcBuffer);         (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);         prevY = srcY;      }      /* store pixel row in destination */      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);   }   _mesa_free(srcBuffer);   _mesa_free(dstBuffer);}#define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) )static INLINE GLfloatlerp_2d(GLfloat a, GLfloat b,        GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11){   const GLfloat temp0 = LERP(a, v00, v10);   const GLfloat temp1 = LERP(a, v01, v11);   return LERP(b, temp0, temp1);}/** * Bilinear interpolation of two source rows. * GLubyte pixels. */static voidresample_linear_row_ub(GLint srcWidth, GLint dstWidth,                       const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,                       GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight){   const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0;   const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1;   GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer;   const GLfloat dstWidthF = (GLfloat) dstWidth;   GLint dstCol;   for (dstCol = 0; dstCol < dstWidth; dstCol++) {      const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF;      GLint srcCol0 = IFLOOR(srcCol);      GLint srcCol1 = srcCol0 + 1;      GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */      GLfloat red, green, blue, alpha;      ASSERT(srcCol0 >= 0);      ASSERT(srcCol0 < srcWidth);      ASSERT(srcCol1 <= srcWidth);      if (srcCol1 == srcWidth) {         /* last column fudge */         srcCol1--;         colWeight = 0.0;      }      if (flip) {         srcCol0 = srcWidth - 1 - srcCol0;         srcCol1 = srcWidth - 1 - srcCol1;      }      red = lerp_2d(colWeight, rowWeight,                    srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],                    srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);      green = lerp_2d(colWeight, rowWeight,                    srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],                    srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);      blue = lerp_2d(colWeight, rowWeight,                    srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],                    srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);      alpha = lerp_2d(colWeight, rowWeight,                    srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],                    srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);            dstColor[dstCol][RCOMP] = IFLOOR(red);      dstColor[dstCol][GCOMP] = IFLOOR(green);      dstColor[dstCol][BCOMP] = IFLOOR(blue);      dstColor[dstCol][ACOMP] = IFLOOR(alpha);   }}/** * Bilinear filtered blit (color only). */static voidblit_linear(GLcontext *ctx,            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1){   struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer;   struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];   const GLint srcWidth = ABS(srcX1 - srcX0);   const GLint dstWidth = ABS(dstX1 - dstX0);   const GLint srcHeight = ABS(srcY1 - srcY0);   const GLint dstHeight = ABS(dstY1 - dstY0);   const GLfloat dstHeightF = (GLfloat) dstHeight;   const GLint srcXpos = MIN2(srcX0, srcX1);   const GLint srcYpos = MIN2(srcY0, srcY1);   const GLint dstXpos = MIN2(dstX0, dstX1);   const GLint dstYpos = MIN2(dstY0, dstY1);   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);   GLint dstRow;   GLint pixelSize;   GLvoid *srcBuffer0, *srcBuffer1;   GLint srcBufferY0 = -1, srcBufferY1 = -1;   GLvoid *dstBuffer;   switch (readRb->DataType) {   case GL_UNSIGNED_BYTE:      pixelSize = 4 * sizeof(GLubyte);      break;   case GL_UNSIGNED_SHORT:      pixelSize = 4 * sizeof(GLushort);      break;   case GL_UNSIGNED_INT:      pixelSize = 4 * sizeof(GLuint);      break;   case GL_FLOAT:      pixelSize = 4 * sizeof(GLfloat);      break;   default:      _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",                    readRb->DataType);      return;   }   /* Allocate the src/dst row buffers.    * Keep two adjacent src rows around for bilinear sampling.    */   srcBuffer0 = _mesa_malloc(pixelSize * srcWidth);   if (!srcBuffer0) {      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");      return;   }   srcBuffer1 = _mesa_malloc(pixelSize * srcWidth);   if (!srcBuffer1) {      _mesa_free(srcBuffer0);      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");      return;   }   dstBuffer = _mesa_malloc(pixelSize * dstWidth);   if (!dstBuffer) {      _mesa_free(srcBuffer0);      _mesa_free(srcBuffer1);      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");      return;   }   for (dstRow = 0; dstRow < dstHeight; dstRow++) {      const GLint dstY = dstYpos + dstRow;      const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;      GLint srcRow0 = IFLOOR(srcRow);      GLint srcRow1 = srcRow0 + 1;      GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */      ASSERT(srcRow >= 0);      ASSERT(srcRow < srcHeight);      if (srcRow1 == srcHeight) {         /* last row fudge */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -