📄 s_drawpix.c
字号:
for (row = 0; row < height; row++, spanY++) {
GLfloat floatSpan[MAX_WIDTH];
const GLvoid *zSrc = _mesa_image_address2d(unpack,
pixels, width, height,
GL_DEPTH_COMPONENT, type,
row, skipPixels);
/* Set these for each row since the _swrast_write_* function may
* change them while clipping.
*/
span.x = spanX;
span.y = spanY;
span.end = spanEnd;
_mesa_unpack_depth_span(ctx, span.end, floatSpan, type,
zSrc, unpack);
/* clamp depth values to [0,1] and convert from floats to ints */
{
GLuint i;
for (i = 0; i < span.end; i++) {
span.array->z[i] = (GLdepth) (floatSpan[i] * depthMax);
}
}
if (zoom) {
_swrast_write_zoomed_depth_span(ctx, &span, desty, skipPixels);
}
else if (ctx->Visual.rgbMode) {
_swrast_write_rgba_span(ctx, &span);
}
else {
_swrast_write_index_span(ctx, &span);
}
}
skipPixels += spanEnd;
}
}
}
/*
* Draw RGBA image.
*/
static void
draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
struct gl_renderbuffer *rb = NULL; /* only used for quickDraw path */
const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
const GLint desty = y;
GLboolean quickDraw;
GLfloat *convImage = NULL;
GLuint transferOps = ctx->_ImageTransferState;
struct sw_span span;
INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glDrawPixels(format or type)");
return;
}
/* Try an optimized glDrawPixels first */
if (fast_draw_pixels(ctx, x, y, width, height, format, type, unpack, pixels))
return;
if (ctx->Depth.Test)
_swrast_span_default_z(ctx, &span);
if (ctx->Fog.Enabled)
_swrast_span_default_fog(ctx, &span);
if (ctx->Texture._EnabledCoordUnits)
_swrast_span_default_texcoords(ctx, &span);
if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 && !zoom && x >= 0 && y >= 0
&& x + width <= (GLint) ctx->DrawBuffer->Width
&& y + height <= (GLint) ctx->DrawBuffer->Height
&& ctx->DrawBuffer->_NumColorDrawBuffers[0] == 1) {
quickDraw = GL_TRUE;
rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
}
else {
quickDraw = GL_FALSE;
rb = NULL;
}
if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
/* Convolution has to be handled specially. We'll create an
* intermediate image, applying all pixel transfer operations
* up to convolution. Then we'll convolve the image. Then
* we'll proceed with the rest of the transfer operations and
* rasterize the image.
*/
GLint row;
GLfloat *dest, *tmpImage;
tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
if (!tmpImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
return;
}
convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
if (!convImage) {
_mesa_free(tmpImage);
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
return;
}
/* Unpack the image and apply transfer ops up to convolution */
dest = tmpImage;
for (row = 0; row < height; row++) {
const GLvoid *source = _mesa_image_address2d(unpack,
pixels, width, height, format, type, row, 0);
_mesa_unpack_color_span_float(ctx, width, GL_RGBA, (GLfloat *) dest,
format, type, source, unpack,
transferOps & IMAGE_PRE_CONVOLUTION_BITS);
dest += width * 4;
}
/* do convolution */
if (ctx->Pixel.Convolution2DEnabled) {
_mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
}
else {
ASSERT(ctx->Pixel.Separable2DEnabled);
_mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
}
_mesa_free(tmpImage);
/* continue transfer ops and draw the convolved image */
unpack = &ctx->DefaultPacking;
pixels = convImage;
format = GL_RGBA;
type = GL_FLOAT;
transferOps &= IMAGE_POST_CONVOLUTION_BITS;
}
/*
* General solution
*/
{
const GLuint interpMask = span.interpMask;
const GLuint arrayMask = span.arrayMask;
GLint row, skipPixels = 0;
/* if the span is wider than MAX_WIDTH we have to do it in chunks */
while (skipPixels < width) {
const GLint spanX = x + (zoom ? 0 : skipPixels);
GLint spanY = y;
const GLint spanEnd = (width - skipPixels > MAX_WIDTH)
? MAX_WIDTH : (width - skipPixels);
ASSERT(span.end <= MAX_WIDTH);
for (row = 0; row < height; row++, spanY++) {
const GLvoid *source = _mesa_image_address2d(unpack,
pixels, width, height, format, type, row, skipPixels);
/* Set these for each row since the _swrast_write_* function may
* change them while clipping.
*/
span.x = spanX;
span.y = spanY;
span.end = spanEnd;
span.arrayMask = arrayMask;
span.interpMask = interpMask;
_mesa_unpack_color_span_chan(ctx, span.end, GL_RGBA,
(GLchan *) span.array->rgba,
format, type, source, unpack,
transferOps);
if ((ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) ||
(ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink))
continue;
if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) {
_swrast_pixel_texture(ctx, &span);
}
/* draw the span */
if (quickDraw) {
rb->PutRow(ctx, rb, span.end, span.x, span.y,
span.array->rgba, NULL);
}
else if (zoom) {
_swrast_write_zoomed_rgba_span(ctx, &span,
(CONST GLchan (*)[4]) span.array->rgba, desty, skipPixels);
}
else {
_swrast_write_rgba_span(ctx, &span);
}
}
skipPixels += spanEnd;
}
}
if (convImage) {
_mesa_free(convImage);
}
}
/*
* Execute glDrawPixels
*/
void
_swrast_DrawPixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->NewState)
_swrast_validate_derived( ctx );
if (unpack->BufferObj->Name) {
/* unpack from PBO */
GLubyte *buf;
if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
format, type, pixels)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glDrawPixels(invalid PBO access)");
return;
}
buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
GL_READ_ONLY_ARB,
unpack->BufferObj);
if (!buf) {
/* buffer is already mapped - that's an error */
_mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(PBO is mapped)");
return;
}
pixels = ADD_POINTERS(buf, pixels);
}
RENDER_START(swrast,ctx);
switch (format) {
case GL_STENCIL_INDEX:
draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels );
break;
case GL_DEPTH_COMPONENT:
draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels );
break;
case GL_COLOR_INDEX:
if (ctx->Visual.rgbMode)
draw_rgba_pixels(ctx, x,y, width, height, format, type, unpack, pixels);
else
draw_index_pixels(ctx, x, y, width, height, type, unpack, pixels);
break;
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_RGB:
case GL_BGR:
case GL_RGBA:
case GL_BGRA:
case GL_ABGR_EXT:
draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels);
break;
default:
_mesa_error( ctx, GL_INVALID_ENUM, "glDrawPixels(format)" );
/* don't return yet, clean-up */
}
RENDER_FINISH(swrast,ctx);
if (unpack->BufferObj->Name) {
/* done with PBO so unmap it now */
ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
unpack->BufferObj);
}
}
#if 0 /* experimental */
/*
* Execute glDrawDepthPixelsMESA().
*/
void
_swrast_DrawDepthPixelsMESA( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum colorFormat, GLenum colorType,
const GLvoid *colors,
GLenum depthType, const GLvoid *depths,
const struct gl_pixelstore_attrib *unpack )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->NewState)
_swrast_validate_derived( ctx );
RENDER_START(swrast,ctx);
switch (colorFormat) {
case GL_COLOR_INDEX:
if (ctx->Visual.rgbMode)
draw_rgba_pixels(ctx, x,y, width, height, colorFormat, colorType, unpack, colors);
else
draw_index_pixels(ctx, x, y, width, height, colorType, unpack, colors);
break;
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_RGB:
case GL_BGR:
case GL_RGBA:
case GL_BGRA:
case GL_ABGR_EXT:
draw_rgba_pixels(ctx, x, y, width, height, colorFormat, colorType, unpack, colors);
break;
default:
_mesa_error( ctx, GL_INVALID_ENUM,
"glDrawDepthPixelsMESA(colorFormat)" );
}
RENDER_FINISH(swrast,ctx);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -