📄 s_copypix.c
字号:
/* Apply shift, offset, look-up table */ if (shift_or_offset) { _mesa_shift_and_offset_ci( ctx, width, span.array->index ); } if (ctx->Pixel.MapColorFlag) { _mesa_map_ci( ctx, width, span.array->index ); } /* write color indexes */ span.x = destx; span.y = dy; span.end = width; if (zoom) _swrast_write_zoomed_index_span(ctx, destx, desty, &span); else _swrast_write_index_span(ctx, &span); } if (overlapping) _mesa_free(tmpImage);}/* * TODO: Optimize!!!! */static voidcopy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty ){ SWcontext *swrast = SWRAST_CONTEXT(ctx); struct gl_framebuffer *fb = ctx->ReadBuffer; struct gl_renderbuffer *readRb = fb->_DepthBuffer; const GLfloat depthMax = fb->_DepthMaxF; GLfloat *p, *tmpImage; GLint sy, dy, stepy; GLint i, j; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; GLint overlapping; struct sw_span span; if (!readRb) { /* no readbuffer - OK */ return; } INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_Z); /* Determine if copy should be bottom-to-top or top-to-bottom */ if (srcy<desty) { /* top-down max-to-min */ sy = srcy + height - 1; dy = desty + height - 1; stepy = -1; } else { /* bottom-up min-to-max */ sy = srcy; dy = desty; stepy = 1; } if (ctx->DrawBuffer == ctx->ReadBuffer) { overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); } else { overlapping = GL_FALSE; } _swrast_span_default_color(ctx, &span); if (swrast->_FogEnabled) _swrast_span_default_fog(ctx, &span); if (overlapping) { GLint ssy = sy; tmpImage = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat)); if (!tmpImage) { _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } p = tmpImage; for (j = 0; j < height; j++, ssy += stepy) { _swrast_read_depth_span_float(ctx, readRb, width, srcx, ssy, p); p += width; } p = tmpImage; } else { tmpImage = NULL; /* silence compiler warning */ p = NULL; } for (j = 0; j < height; j++, sy += stepy, dy += stepy) { GLfloat depth[MAX_WIDTH]; /* get depth values */ if (overlapping) { _mesa_memcpy(depth, p, width * sizeof(GLfloat)); p += width; } else { _swrast_read_depth_span_float(ctx, readRb, width, srcx, sy, depth); } /* apply scale and bias */ for (i = 0; i < width; i++) { GLfloat d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias; span.array->z[i] = (GLuint) (CLAMP(d, 0.0F, 1.0F) * depthMax); } /* write depth values */ span.x = destx; span.y = dy; span.end = width; if (fb->Visual.rgbMode) { if (zoom) _swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, (const GLchan (*)[4]) span.array->rgba); else _swrast_write_rgba_span(ctx, &span); } else { if (zoom) _swrast_write_zoomed_index_span(ctx, destx, desty, &span); else _swrast_write_index_span(ctx, &span); } } if (overlapping) _mesa_free(tmpImage);}static voidcopy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty ){ struct gl_framebuffer *fb = ctx->ReadBuffer; struct gl_renderbuffer *rb = fb->_StencilBuffer; GLint sy, dy, stepy; GLint j; GLstencil *p, *tmpImage; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset; GLint overlapping; if (!rb) { /* no readbuffer - OK */ return; } /* Determine if copy should be bottom-to-top or top-to-bottom */ if (srcy < desty) { /* top-down max-to-min */ sy = srcy + height - 1; dy = desty + height - 1; stepy = -1; } else { /* bottom-up min-to-max */ sy = srcy; dy = desty; stepy = 1; } if (ctx->DrawBuffer == ctx->ReadBuffer) { overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); } else { overlapping = GL_FALSE; } if (overlapping) { GLint ssy = sy; tmpImage = (GLstencil *) _mesa_malloc(width * height * sizeof(GLstencil)); if (!tmpImage) { _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } p = tmpImage; for (j = 0; j < height; j++, ssy += stepy) { _swrast_read_stencil_span( ctx, rb, width, srcx, ssy, p ); p += width; } p = tmpImage; } else { tmpImage = NULL; /* silence compiler warning */ p = NULL; } for (j = 0; j < height; j++, sy += stepy, dy += stepy) { GLstencil stencil[MAX_WIDTH]; /* Get stencil values */ if (overlapping) { _mesa_memcpy(stencil, p, width * sizeof(GLstencil)); p += width; } else { _swrast_read_stencil_span( ctx, rb, width, srcx, sy, stencil ); } /* Apply shift, offset, look-up table */ if (shift_or_offset) { _mesa_shift_and_offset_stencil( ctx, width, stencil ); } if (ctx->Pixel.MapStencilFlag) { _mesa_map_stencil( ctx, width, stencil ); } /* Write stencil values */ if (zoom) { _swrast_write_zoomed_stencil_span(ctx, destx, desty, width, destx, dy, stencil); } else { _swrast_write_stencil_span( ctx, width, destx, dy, stencil ); } } if (overlapping) _mesa_free(tmpImage);}/** * This isn't terribly efficient. If a driver really has combined * depth/stencil buffers the driver should implement an optimized * CopyPixels function. */static voidcopy_depth_stencil_pixels(GLcontext *ctx, const GLint srcX, const GLint srcY, const GLint width, const GLint height, const GLint destX, const GLint destY){ struct gl_renderbuffer *stencilReadRb, *depthReadRb, *depthDrawRb; GLint sy, dy, stepy; GLint j; GLstencil *tempStencilImage = NULL, *stencilPtr = NULL; GLfloat *tempDepthImage = NULL, *depthPtr = NULL; const GLfloat depthScale = ctx->DrawBuffer->_DepthMaxF; const GLuint stencilMask = ctx->Stencil.WriteMask[0]; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; const GLboolean shiftOrOffset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset; const GLboolean scaleOrBias = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0; GLint overlapping; depthDrawRb = ctx->DrawBuffer->_DepthBuffer; depthReadRb = ctx->ReadBuffer->_DepthBuffer; stencilReadRb = ctx->ReadBuffer->_StencilBuffer; ASSERT(depthDrawRb); ASSERT(depthReadRb); ASSERT(stencilReadRb); /* Determine if copy should be bottom-to-top or top-to-bottom */ if (srcY < destY) { /* top-down max-to-min */ sy = srcY + height - 1; dy = destY + height - 1; stepy = -1; } else { /* bottom-up min-to-max */ sy = srcY; dy = destY; stepy = 1; } if (ctx->DrawBuffer == ctx->ReadBuffer) { overlapping = regions_overlap(srcX, srcY, destX, destY, width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); } else { overlapping = GL_FALSE; } if (overlapping) { GLint ssy = sy; if (stencilMask != 0x0) { tempStencilImage = (GLstencil *) _mesa_malloc(width * height * sizeof(GLstencil)); if (!tempStencilImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); return; } /* get copy of stencil pixels */ stencilPtr = tempStencilImage; for (j = 0; j < height; j++, ssy += stepy) { _swrast_read_stencil_span(ctx, stencilReadRb, width, srcX, ssy, stencilPtr); stencilPtr += width; } stencilPtr = tempStencilImage; } if (ctx->Depth.Mask) { tempDepthImage = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat)); if (!tempDepthImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); _mesa_free(tempStencilImage); return; } /* get copy of depth pixels */ depthPtr = tempDepthImage; for (j = 0; j < height; j++, ssy += stepy) { _swrast_read_depth_span_float(ctx, depthReadRb, width, srcX, ssy, depthPtr); depthPtr += width; } depthPtr = tempDepthImage; } } for (j = 0; j < height; j++, sy += stepy, dy += stepy) { if (stencilMask != 0x0) { GLstencil stencil[MAX_WIDTH]; /* Get stencil values */ if (overlapping) { _mesa_memcpy(stencil, stencilPtr, width * sizeof(GLstencil)); stencilPtr += width; } else { _swrast_read_stencil_span(ctx, stencilReadRb, width, srcX, sy, stencil); } /* Apply shift, offset, look-up table */ if (shiftOrOffset) { _mesa_shift_and_offset_stencil(ctx, width, stencil); } if (ctx->Pixel.MapStencilFlag) { _mesa_map_stencil(ctx, width, stencil); } /* Write values */ if (zoom) { _swrast_write_zoomed_stencil_span(ctx, destX, destY, width, destX, dy, stencil); } else { _swrast_write_stencil_span( ctx, width, destX, dy, stencil ); } } if (ctx->Depth.Mask) { GLfloat depth[MAX_WIDTH]; GLuint zVals32[MAX_WIDTH]; GLushort zVals16[MAX_WIDTH]; GLvoid *zVals; GLuint zBytes; /* get depth values */ if (overlapping) { _mesa_memcpy(depth, depthPtr, width * sizeof(GLfloat)); depthPtr += width; } else { _swrast_read_depth_span_float(ctx, depthReadRb, width, srcX, sy, depth); } /* scale & bias */ if (scaleOrBias) { _mesa_scale_and_bias_depth(ctx, width, depth); } /* convert to integer Z values */ if (depthDrawRb->DataType == GL_UNSIGNED_SHORT) { GLint k; for (k = 0; k < width; k++) zVals16[k] = (GLushort) (depth[k] * depthScale); zVals = zVals16; zBytes = 2; } else { GLint k; for (k = 0; k < width; k++) zVals32[k] = (GLuint) (depth[k] * depthScale); zVals = zVals32; zBytes = 4; } /* Write values */ if (zoom) { _swrast_write_zoomed_z_span(ctx, destX, destY, width, destX, dy, zVals); } else { _swrast_put_row(ctx, depthDrawRb, width, destX, dy, zVals, zBytes); } } } if (tempStencilImage) _mesa_free(tempStencilImage); if (tempDepthImage) _mesa_free(tempDepthImage);}/** * Do software-based glCopyPixels. * By time we get here, all parameters will have been error-checked. */void_swrast_CopyPixels( GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint destx, GLint desty, GLenum type ){ SWcontext *swrast = SWRAST_CONTEXT(ctx); RENDER_START(swrast,ctx); if (swrast->NewState) _swrast_validate_derived( ctx ); switch (type) { case GL_COLOR: if (ctx->Visual.rgbMode) { copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty ); } else { copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty ); } break; case GL_DEPTH: copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty ); break; case GL_STENCIL: copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty ); break; case GL_DEPTH_STENCIL_EXT: copy_depth_stencil_pixels(ctx, srcx, srcy, width, height, destx, desty); break; default: _mesa_problem(ctx, "unexpected type in _swrast_CopyPixels"); } RENDER_FINISH(swrast,ctx);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -