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

📄 s_blit.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 2 页
字号:
         srcRow1 = srcRow0;         rowWeight = 0.0;      }      if (invertY) {         srcRow0 = srcHeight - 1 - srcRow0;         srcRow1 = srcHeight - 1 - srcRow1;      }      srcY0 = srcYpos + srcRow0;      srcY1 = srcYpos + srcRow1;      /* get the two source rows */      if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {         /* use same source row buffers again */      }      else if (srcY0 == srcBufferY1) {         /* move buffer1 into buffer0 by swapping pointers */         GLvoid *tmp = srcBuffer0;         srcBuffer0 = srcBuffer1;         srcBuffer1 = tmp;         /* get y1 row */         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);         srcBufferY0 = srcY0;         srcBufferY1 = srcY1;      }      else {         /* get both new rows */         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY0, srcBuffer0);         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);         srcBufferY0 = srcY0;         srcBufferY1 = srcY1;      }      if (readRb->DataType == GL_UNSIGNED_BYTE) {         resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,                                dstBuffer, invertX, rowWeight);      }      else {         _mesa_problem(ctx, "Unsupported color channel type in sw blit");         break;      }      /* store pixel row in destination */      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);   }   _mesa_free(srcBuffer0);   _mesa_free(srcBuffer1);   _mesa_free(dstBuffer);}/** * Simple case:  Blit color, depth or stencil with no scaling or flipping. * XXX we could easily support vertical flipping here. */static voidsimple_blit(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 width = srcX1 - srcX0;   const GLint height = srcY1 - srcY0;   GLint row, srcY, dstY, yStep;   GLint comps, bytesPerRow;   void *rowBuffer;   /* only one buffer */   ASSERT(_mesa_bitcount(buffer) == 1);   /* no flipping checks */   ASSERT(srcX0 < srcX1);   ASSERT(srcY0 < srcY1);   ASSERT(dstX0 < dstX1);   ASSERT(dstY0 < dstY1);   /* size checks */   ASSERT(srcX1 - srcX0 == dstX1 - dstX0);   ASSERT(srcY1 - srcY0 == dstY1 - dstY0);   /* determine if copy should be bottom-to-top or top-to-bottom */   if (srcY0 > dstY0) {      /* src above dst: copy bottom-to-top */      yStep = 1;      srcY = srcY0;      dstY = dstY0;   }   else {      /* src below dst: copy top-to-bottom */      yStep = -1;      srcY = srcY1 - 1;      dstY = dstY1 - 1;   }   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 simple_blit()");      return;   }   ASSERT(readRb->DataType == drawRb->DataType);   /* compute bytes per row */   switch (readRb->DataType) {   case GL_UNSIGNED_BYTE:      bytesPerRow = comps * width * sizeof(GLubyte);      break;   case GL_UNSIGNED_SHORT:      bytesPerRow = comps * width * sizeof(GLushort);      break;   case GL_UNSIGNED_INT:      bytesPerRow = comps * width * sizeof(GLuint);      break;   case GL_FLOAT:      bytesPerRow = comps * width * sizeof(GLfloat);      break;   default:      _mesa_problem(ctx, "unexpected buffer type in simple_blit");      return;   }   /* allocate the row buffer */   rowBuffer = _mesa_malloc(bytesPerRow);   if (!rowBuffer) {      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");      return;   }   for (row = 0; row < height; row++) {      readRb->GetRow(ctx, readRb, width, srcX0, srcY, rowBuffer);      drawRb->PutRow(ctx, drawRb, width, dstX0, dstY, rowBuffer, NULL);      srcY += yStep;      dstY += yStep;   }   _mesa_free(rowBuffer);}/** * Clip dst coords against Xmax (or Ymax). */static INLINE voidclip_right_or_top(GLint *srcX0, GLint *srcX1,                  GLint *dstX0, GLint *dstX1,                  GLint maxValue){   GLfloat t, bias;   if (*dstX1 > maxValue) {      /* X1 outside right edge */      ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */      t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);      /* chop off [t, 1] part */      ASSERT(t >= 0.0 && t <= 1.0);      *dstX1 = maxValue;      bias = (*srcX0 < *srcX1) ? 0.5 : -0.5;      *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);   }   else if (*dstX0 > maxValue) {      /* X0 outside right edge */      ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */      t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);      /* chop off [t, 1] part */      ASSERT(t >= 0.0 && t <= 1.0);      *dstX0 = maxValue;      bias = (*srcX0 < *srcX1) ? -0.5 : 0.5;      *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);   }}/** * Clip dst coords against Xmin (or Ymin). */static INLINE voidclip_left_or_bottom(GLint *srcX0, GLint *srcX1,                    GLint *dstX0, GLint *dstX1,                    GLint minValue){   GLfloat t, bias;   if (*dstX0 < minValue) {      /* X0 outside left edge */      ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */      t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);      /* chop off [0, t] part */      ASSERT(t >= 0.0 && t <= 1.0);      *dstX0 = minValue;      bias = (*srcX0 < *srcX1) ? 0.5 : -0.5; /* flipped??? */      *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);   }   else if (*dstX1 < minValue) {      /* X1 outside left edge */      ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */      t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);      /* chop off [0, t] part */      ASSERT(t >= 0.0 && t <= 1.0);      *dstX1 = minValue;      bias = (*srcX0 < *srcX1) ? 0.5 : -0.5;      *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);   }}/** * Do clipping of blit src/dest rectangles. * The dest rect is clipped against both the buffer bounds and scissor bounds. * The src rect is just clipped against the buffer bounds. * * When either the src or dest rect is clipped, the other is also clipped * proportionately! * * Note that X0 need not be less than X1 (same for Y) for either the source * and dest rects.  That makes the clipping a little trickier. * * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped */static GLbooleanclip_blit(GLcontext *ctx,          GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1,          GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1){   const GLint srcXmin = 0;   const GLint srcXmax = ctx->ReadBuffer->Width;   const GLint srcYmin = 0;   const GLint srcYmax = ctx->ReadBuffer->Height;   /* these include scissor bounds */   const GLint dstXmin = ctx->DrawBuffer->_Xmin;   const GLint dstXmax = ctx->DrawBuffer->_Xmax;   const GLint dstYmin = ctx->DrawBuffer->_Ymin;   const GLint dstYmax = ctx->DrawBuffer->_Ymax;   /*   printf("PreClipX:  src: %d .. %d  dst: %d .. %d\n",          *srcX0, *srcX1, *dstX0, *dstX1);   printf("PreClipY:  src: %d .. %d  dst: %d .. %d\n",          *srcY0, *srcY1, *dstY0, *dstY1);   */   /* trivial rejection tests */   if (*dstX0 == *dstX1)      return GL_FALSE; /* no width */   if (*dstX0 <= dstXmin && *dstX1 <= dstXmin)      return GL_FALSE; /* totally out (left) of bounds */   if (*dstX0 >= dstXmax && *dstX1 >= dstXmax)      return GL_FALSE; /* totally out (right) of bounds */   if (*dstY0 == *dstY1)      return GL_FALSE;   if (*dstY0 <= dstYmin && *dstY1 <= dstYmin)      return GL_FALSE;   if (*dstY0 >= dstYmax && *dstY1 >= dstYmax)      return GL_FALSE;   if (*srcX0 == *srcX1)      return GL_FALSE;   if (*srcX0 <= srcXmin && *srcX1 <= srcXmin)      return GL_FALSE;   if (*srcX0 >= srcXmax && *srcX1 >= srcXmax)      return GL_FALSE;   if (*srcY0 == *srcY1)      return GL_FALSE;   if (*srcY0 <= srcYmin && *srcY1 <= srcYmin)      return GL_FALSE;   if (*srcY0 >= srcYmax && *srcY1 >= srcYmax)      return GL_FALSE;   /*    * dest clip    */   clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax);   clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax);   clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin);   clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin);   /*    * src clip (just swap src/dst values from above)    */   clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax);   clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax);   clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin);   clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin);   /*   printf("PostClipX: src: %d .. %d  dst: %d .. %d\n",          *srcX0, *srcX1, *dstX0, *dstX1);   printf("PostClipY: src: %d .. %d  dst: %d .. %d\n",          *srcY0, *srcY1, *dstY0, *dstY1);   */   ASSERT(*dstX0 >= dstXmin);   ASSERT(*dstX0 <= dstXmax);   ASSERT(*dstX1 >= dstXmin);   ASSERT(*dstX1 <= dstXmax);   ASSERT(*dstY0 >= dstYmin);   ASSERT(*dstY0 <= dstYmax);   ASSERT(*dstY1 >= dstYmin);   ASSERT(*dstY1 <= dstYmax);   ASSERT(*srcX0 >= srcXmin);   ASSERT(*srcX0 <= srcXmax);   ASSERT(*srcX1 >= srcXmin);   ASSERT(*srcX1 <= srcXmax);   ASSERT(*srcY0 >= srcYmin);   ASSERT(*srcY0 <= srcYmax);   ASSERT(*srcY1 >= srcYmin);   ASSERT(*srcY1 <= srcYmax);   return GL_TRUE;}/** * Software fallback for glBlitFramebufferEXT(). */void_swrast_BlitFramebuffer(GLcontext *ctx,                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,                        GLbitfield mask, GLenum filter){   SWcontext *swrast = SWRAST_CONTEXT(ctx);   static const GLint buffers[3] = {      GL_COLOR_BUFFER_BIT,      GL_DEPTH_BUFFER_BIT,      GL_STENCIL_BUFFER_BIT   };   GLint i;   if (!ctx->DrawBuffer->_NumColorDrawBuffers)      return;   if (!clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,                  &dstX0, &dstY0, &dstX1, &dstY1)) {      return;   }   RENDER_START(swrast, ctx);   if (srcX1 - srcX0 == dstX1 - dstX0 &&       srcY1 - srcY0 == dstY1 - dstY0 &&       srcX0 < srcX1 &&       srcY0 < srcY1 &&       dstX0 < dstX1 &&       dstY0 < dstY1) {      /* no stretching or flipping.       * filter doesn't matter.       */      for (i = 0; i < 3; i++) {         if (mask & buffers[i]) {            simple_blit(ctx, srcX0, srcY0, srcX1, srcY1,                        dstX0, dstY0, dstX1, dstY1, buffers[i]);         }      }   }   else {      if (filter == GL_NEAREST) {         for (i = 0; i < 3; i++) {            if (mask & buffers[i]) {               blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,                            dstX0, dstY0, dstX1, dstY1, buffers[i]);            }         }      }      else {         ASSERT(filter == GL_LINEAR);         if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */            blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,                        dstX0, dstY0, dstX1, dstY1);         }      }   }   RENDER_FINISH(swrast, ctx);}

⌨️ 快捷键说明

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