Lots of changes to support runtime renderbuffer depths.
_swrast_read_rgba_span() now takes a datatype parameter. New optimization for glReadPixels(format=GL_RGB). New glCopyPixels optimization for the simple, common cases.
This commit is contained in:
@@ -307,7 +307,7 @@ accum_accum(GLcontext *ctx, GLfloat value,
|
||||
|
||||
/* read colors from color buffer */
|
||||
_swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width,
|
||||
xpos, ypos + i, rgba);
|
||||
xpos, ypos + i, CHAN_TYPE, rgba);
|
||||
|
||||
/* do accumulation */
|
||||
if (swrast->_IntegerAccumMode) {
|
||||
@@ -391,7 +391,7 @@ accum_load(GLcontext *ctx, GLfloat value,
|
||||
|
||||
/* read colors from color buffer */
|
||||
_swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width,
|
||||
xpos, ypos + i, rgba);
|
||||
xpos, ypos + i, CHAN_TYPE, rgba);
|
||||
|
||||
/* do load */
|
||||
if (swrast->_IntegerAccumMode) {
|
||||
|
@@ -432,6 +432,16 @@ _swrast_validate_derived( GLcontext *ctx );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Size of an RGBA pixel, in bytes, for given datatype.
|
||||
*/
|
||||
#define RGBA_PIXEL_SIZE(TYPE) \
|
||||
((TYPE == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) : \
|
||||
((TYPE == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort) \
|
||||
: 4 * sizeof(GLfloat)))
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* XXX these macros are just bandages for now in order to make
|
||||
* CHAN_BITS==32 compile cleanly.
|
||||
|
@@ -41,11 +41,12 @@
|
||||
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
* Determine if there's overlap in an image copy.
|
||||
* This test also compensates for the fact that copies are done from
|
||||
* bottom to top and overlaps can sometimes be handled correctly
|
||||
* without making a temporary image copy.
|
||||
* \return GL_TRUE if the regions overlap, GL_FALSE otherwise.
|
||||
*/
|
||||
static GLboolean
|
||||
regions_overlap(GLint srcx, GLint srcy,
|
||||
@@ -87,41 +88,6 @@ regions_overlap(GLint srcx, GLint srcy,
|
||||
|
||||
|
||||
/**
|
||||
* Convert GLfloat[n][4] colors to GLchan[n][4].
|
||||
* XXX maybe move into image.c
|
||||
*/
|
||||
static void
|
||||
float_span_to_chan(GLuint n, CONST GLfloat in[][4], GLchan out[][4])
|
||||
{
|
||||
GLuint i;
|
||||
for (i = 0; i < n; i++) {
|
||||
UNCLAMPED_FLOAT_TO_CHAN(out[i][RCOMP], in[i][RCOMP]);
|
||||
UNCLAMPED_FLOAT_TO_CHAN(out[i][GCOMP], in[i][GCOMP]);
|
||||
UNCLAMPED_FLOAT_TO_CHAN(out[i][BCOMP], in[i][BCOMP]);
|
||||
UNCLAMPED_FLOAT_TO_CHAN(out[i][ACOMP], in[i][ACOMP]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert GLchan[n][4] colors to GLfloat[n][4].
|
||||
* XXX maybe move into image.c
|
||||
*/
|
||||
static void
|
||||
chan_span_to_float(GLuint n, CONST GLchan in[][4], GLfloat out[][4])
|
||||
{
|
||||
GLuint i;
|
||||
for (i = 0; i < n; i++) {
|
||||
out[i][RCOMP] = CHAN_TO_FLOAT(in[i][RCOMP]);
|
||||
out[i][GCOMP] = CHAN_TO_FLOAT(in[i][GCOMP]);
|
||||
out[i][BCOMP] = CHAN_TO_FLOAT(in[i][BCOMP]);
|
||||
out[i][ACOMP] = CHAN_TO_FLOAT(in[i][ACOMP]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* RGBA copypixels with convolution.
|
||||
*/
|
||||
static void
|
||||
@@ -129,11 +95,11 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
|
||||
GLint width, GLint height, GLint destx, GLint desty)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
struct gl_renderbuffer *drawRb = NULL;
|
||||
GLboolean quick_draw;
|
||||
GLint row;
|
||||
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
|
||||
const GLuint transferOps = ctx->_ImageTransferState;
|
||||
const GLboolean sink = (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink)
|
||||
|| (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink);
|
||||
GLfloat *dest, *tmpImage, *convImage;
|
||||
SWspan span;
|
||||
|
||||
@@ -145,17 +111,6 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
|
||||
_swrast_span_default_fog(ctx, &span);
|
||||
|
||||
|
||||
if (SWRAST_CONTEXT(ctx)->_RasterMask == 0
|
||||
&& !zoom
|
||||
&& destx >= 0
|
||||
&& destx + width <= (GLint) ctx->DrawBuffer->Width) {
|
||||
quick_draw = GL_TRUE;
|
||||
drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
|
||||
}
|
||||
else {
|
||||
quick_draw = GL_FALSE;
|
||||
}
|
||||
|
||||
/* allocate space for GLfloat image */
|
||||
tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
|
||||
if (!tmpImage) {
|
||||
@@ -169,15 +124,11 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
|
||||
return;
|
||||
}
|
||||
|
||||
/* read source image */
|
||||
/* read source image as float/RGBA */
|
||||
dest = tmpImage;
|
||||
for (row = 0; row < height; row++) {
|
||||
GLchan rgba[MAX_WIDTH][4];
|
||||
/* Read GLchan and convert to GLfloat */
|
||||
_swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer,
|
||||
width, srcx, srcy + row, rgba);
|
||||
chan_span_to_float(width, (CONST GLchan (*)[4]) rgba,
|
||||
(GLfloat (*)[4]) dest);
|
||||
width, srcx, srcy + row, GL_FLOAT, dest);
|
||||
dest += 4 * width;
|
||||
}
|
||||
|
||||
@@ -207,38 +158,36 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
|
||||
width, rgba);
|
||||
}
|
||||
|
||||
if (!sink) {
|
||||
/* write the new image */
|
||||
for (row = 0; row < height; row++) {
|
||||
const GLfloat *src = convImage + row * width * 4;
|
||||
GLint dy;
|
||||
GLvoid *rgba = span.array->color.sz1.rgba; /* row storage */
|
||||
|
||||
/* convert floats back to chan */
|
||||
float_span_to_chan(width, (const GLfloat (*)[4]) src, span.array->rgba);
|
||||
/* copy convolved colors into span array */
|
||||
_mesa_memcpy(rgba, src, width * 4 * sizeof(GLfloat));
|
||||
|
||||
/* write row to framebuffer */
|
||||
dy = desty + row;
|
||||
if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) {
|
||||
drawRb->PutRow(ctx, drawRb, width, destx, dy, span.array->rgba, NULL);
|
||||
}
|
||||
else {
|
||||
/* write span */
|
||||
span.x = destx;
|
||||
span.y = dy;
|
||||
span.y = desty + row;
|
||||
span.end = width;
|
||||
span.array->ChanType = GL_FLOAT;
|
||||
if (zoom) {
|
||||
_swrast_write_zoomed_rgba_span(ctx, destx, desty, &span,
|
||||
span.array->rgba);
|
||||
_swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, rgba);
|
||||
}
|
||||
else {
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
}
|
||||
}
|
||||
/* restore this */
|
||||
span.array->ChanType = CHAN_TYPE;
|
||||
}
|
||||
|
||||
_mesa_free(convImage);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
* RGBA copypixels
|
||||
*/
|
||||
static void
|
||||
@@ -246,10 +195,8 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
|
||||
GLint width, GLint height, GLint destx, GLint desty)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
struct gl_renderbuffer *drawRb;
|
||||
GLchan *tmpImage,*p;
|
||||
GLboolean quick_draw;
|
||||
GLint sy, dy, stepy, j;
|
||||
GLfloat *tmpImage, *p;
|
||||
GLint sy, dy, stepy, row;
|
||||
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
|
||||
GLint overlapping;
|
||||
const GLuint transferOps = ctx->_ImageTransferState;
|
||||
@@ -260,8 +207,6 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
|
||||
return;
|
||||
}
|
||||
|
||||
INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
|
||||
|
||||
if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
|
||||
copy_conv_rgba_pixels(ctx, srcx, srcy, width, height, destx, desty);
|
||||
return;
|
||||
@@ -289,35 +234,23 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
|
||||
overlapping = GL_FALSE;
|
||||
}
|
||||
|
||||
INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
|
||||
if (ctx->Depth.Test)
|
||||
_swrast_span_default_z(ctx, &span);
|
||||
if (swrast->_FogEnabled)
|
||||
_swrast_span_default_fog(ctx, &span);
|
||||
|
||||
if (SWRAST_CONTEXT(ctx)->_RasterMask == 0
|
||||
&& !zoom
|
||||
&& destx >= 0
|
||||
&& destx + width <= (GLint) ctx->DrawBuffer->Width) {
|
||||
quick_draw = GL_TRUE;
|
||||
drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
|
||||
}
|
||||
else {
|
||||
quick_draw = GL_FALSE;
|
||||
drawRb = NULL;
|
||||
}
|
||||
|
||||
if (overlapping) {
|
||||
GLint ssy = sy;
|
||||
tmpImage = (GLchan *) _mesa_malloc(width * height * sizeof(GLchan) * 4);
|
||||
tmpImage = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat) * 4);
|
||||
if (!tmpImage) {
|
||||
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
|
||||
return;
|
||||
}
|
||||
/* read the source image */
|
||||
/* read the source image as RGBA/float */
|
||||
p = tmpImage;
|
||||
for (j = 0; j < height; j++, ssy += stepy) {
|
||||
for (row = 0; row < height; row++) {
|
||||
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
|
||||
width, srcx, ssy, (GLchan (*)[4]) p );
|
||||
width, srcx, sy + row, GL_FLOAT, p );
|
||||
p += width * 4;
|
||||
}
|
||||
p = tmpImage;
|
||||
@@ -327,48 +260,42 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
|
||||
/* Get source pixels */
|
||||
ASSERT(width < MAX_WIDTH);
|
||||
|
||||
for (row = 0; row < height; row++, sy += stepy, dy += stepy) {
|
||||
GLvoid *rgba = span.array->color.sz4.rgba;
|
||||
|
||||
/* Get row/span of source pixels */
|
||||
if (overlapping) {
|
||||
/* get from buffered image */
|
||||
ASSERT(width < MAX_WIDTH);
|
||||
_mesa_memcpy(span.array->rgba, p, width * sizeof(GLchan) * 4);
|
||||
_mesa_memcpy(rgba, p, width * sizeof(GLfloat) * 4);
|
||||
p += width * 4;
|
||||
}
|
||||
else {
|
||||
/* get from framebuffer */
|
||||
ASSERT(width < MAX_WIDTH);
|
||||
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
|
||||
width, srcx, sy, span.array->rgba );
|
||||
width, srcx, sy, GL_FLOAT, rgba );
|
||||
}
|
||||
|
||||
if (transferOps) {
|
||||
GLfloat rgbaFloat[MAX_WIDTH][4];
|
||||
/* convert to float, transfer, convert back to chan */
|
||||
chan_span_to_float(width, (CONST GLchan (*)[4]) span.array->rgba,
|
||||
rgbaFloat);
|
||||
_mesa_apply_rgba_transfer_ops(ctx, transferOps, width, rgbaFloat);
|
||||
float_span_to_chan(width, (CONST GLfloat (*)[4]) rgbaFloat,
|
||||
span.array->rgba);
|
||||
_mesa_apply_rgba_transfer_ops(ctx, transferOps, width,
|
||||
(GLfloat (*)[4]) rgba);
|
||||
}
|
||||
|
||||
/* Write color span */
|
||||
if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) {
|
||||
drawRb->PutRow(ctx, drawRb, width, destx, dy, span.array->rgba, NULL);
|
||||
}
|
||||
else {
|
||||
span.x = destx;
|
||||
span.y = dy;
|
||||
span.end = width;
|
||||
span.array->ChanType = GL_FLOAT;
|
||||
if (zoom) {
|
||||
_swrast_write_zoomed_rgba_span(ctx, destx, desty, &span,
|
||||
span.array->rgba);
|
||||
_swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, rgba);
|
||||
}
|
||||
else {
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
span.array->ChanType = CHAN_TYPE; /* restore */
|
||||
|
||||
if (overlapping)
|
||||
_mesa_free(tmpImage);
|
||||
@@ -902,6 +829,87 @@ copy_depth_stencil_pixels(GLcontext *ctx,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Try to do a fast copy pixels.
|
||||
*/
|
||||
static GLboolean
|
||||
fast_copy_pixels(GLcontext *ctx,
|
||||
GLint srcX, GLint srcY, GLsizei width, GLsizei height,
|
||||
GLint dstX, GLint dstY, GLenum type)
|
||||
{
|
||||
struct gl_framebuffer *srcFb = ctx->ReadBuffer;
|
||||
struct gl_framebuffer *dstFb = ctx->DrawBuffer;
|
||||
struct gl_renderbuffer *srcRb, *dstRb;
|
||||
GLint row, yStep;
|
||||
|
||||
if (SWRAST_CONTEXT(ctx)->_RasterMask != 0x0 ||
|
||||
ctx->Pixel.ZoomX != 1.0F ||
|
||||
ctx->Pixel.ZoomY != 1.0F ||
|
||||
ctx->_ImageTransferState) {
|
||||
/* can't handle these */
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (type == GL_COLOR) {
|
||||
if (dstFb->_NumColorDrawBuffers[0] != 1)
|
||||
return GL_FALSE;
|
||||
srcRb = srcFb->_ColorReadBuffer;
|
||||
dstRb = dstFb->_ColorDrawBuffers[0][0];
|
||||
}
|
||||
else if (type == GL_STENCIL) {
|
||||
srcRb = srcFb->_StencilBuffer;
|
||||
dstRb = dstFb->_StencilBuffer;
|
||||
}
|
||||
else if (type == GL_DEPTH) {
|
||||
srcRb = srcFb->_DepthBuffer;
|
||||
dstRb = dstFb->_DepthBuffer;
|
||||
}
|
||||
else if (type == GL_DEPTH_STENCIL_EXT) {
|
||||
/* XXX correct? */
|
||||
srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
}
|
||||
|
||||
/* src and dst renderbuffers must be same format and type */
|
||||
if (!srcRb || !dstRb ||
|
||||
srcRb->DataType != dstRb->DataType ||
|
||||
srcRb->_BaseFormat != dstRb->_BaseFormat) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* clipping not supported */
|
||||
if (srcX < 0 || srcX + width > srcFb->Width ||
|
||||
srcY < 0 || srcY + height > srcFb->Width ||
|
||||
dstX < dstFb->_Xmin || dstX + width > dstFb->_Xmax ||
|
||||
dstY < dstFb->_Ymin || dstY + height > dstFb->_Ymax) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* overlapping src/dst doesn't matter, just determine Y direction */
|
||||
if (srcY < dstY) {
|
||||
/* top-down max-to-min */
|
||||
srcY = srcY + height - 1;
|
||||
dstY = dstY + height - 1;
|
||||
yStep = -1;
|
||||
}
|
||||
else {
|
||||
/* bottom-up min-to-max */
|
||||
yStep = 1;
|
||||
}
|
||||
|
||||
for (row = 0; row < height; row++) {
|
||||
GLuint temp[MAX_WIDTH][4];
|
||||
srcRb->GetRow(ctx, srcRb, width, srcX, srcY, temp);
|
||||
dstRb->PutRow(ctx, dstRb, width, dstX, dstY, temp, NULL);
|
||||
srcY += yStep;
|
||||
dstY += yStep;
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do software-based glCopyPixels.
|
||||
* By time we get here, all parameters will have been error-checked.
|
||||
@@ -917,6 +925,7 @@ _swrast_CopyPixels( GLcontext *ctx,
|
||||
if (swrast->NewState)
|
||||
_swrast_validate_derived( ctx );
|
||||
|
||||
if (!fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type)) {
|
||||
switch (type) {
|
||||
case GL_COLOR:
|
||||
if (ctx->Visual.rgbMode) {
|
||||
@@ -938,6 +947,7 @@ _swrast_CopyPixels( GLcontext *ctx,
|
||||
default:
|
||||
_mesa_problem(ctx, "unexpected type in _swrast_CopyPixels");
|
||||
}
|
||||
}
|
||||
|
||||
RENDER_FINISH(swrast,ctx);
|
||||
}
|
||||
|
@@ -40,12 +40,13 @@
|
||||
#include "s_zoom.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Try to do a fast and simple RGB(a) glDrawPixels.
|
||||
* Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
|
||||
*/
|
||||
static GLboolean
|
||||
fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
|
||||
fast_draw_rgba_pixels(GLcontext *ctx, GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *userUnpack,
|
||||
@@ -63,7 +64,6 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
|
||||
|
||||
if ((swrast->_RasterMask & ~CLIP_BIT) ||
|
||||
ctx->Texture._EnabledCoordUnits ||
|
||||
userUnpack->Alignment != 1 ||
|
||||
userUnpack->SwapBytes ||
|
||||
ctx->_ImageTransferState) {
|
||||
/* can't handle any of those conditions */
|
||||
@@ -100,26 +100,25 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
|
||||
else {
|
||||
/* non-simple zooming */
|
||||
simpleZoom = GL_FALSE;
|
||||
yStep = 1;
|
||||
if (unpack.RowLength == 0)
|
||||
unpack.RowLength = width;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ready to draw!
|
||||
* The window region at (destX, destY) of size (drawWidth, drawHeight)
|
||||
* will be written to.
|
||||
* We'll take pixel data from buffer pointed to by "pixels" but we'll
|
||||
* skip "unpack.SkipRows" rows and skip "unpack.SkipPixels" pixels/row.
|
||||
*/
|
||||
|
||||
if (format == GL_RGBA && type == CHAN_TYPE && rbType == CHAN_TYPE) {
|
||||
const GLchan *src = (const GLchan *) pixels
|
||||
+ (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels) * 4;
|
||||
if (format == GL_RGBA && type == rbType) {
|
||||
const GLubyte *src = _mesa_image_address2d(&unpack, pixels, width,
|
||||
height, format, type, 0, 0);
|
||||
const GLint srcStride = _mesa_image_row_stride(&unpack, width,
|
||||
format, type);
|
||||
if (simpleZoom) {
|
||||
GLint row;
|
||||
for (row = 0; row < drawHeight; row++) {
|
||||
rb->PutRow(ctx, rb, drawWidth, destX, destY, src, NULL);
|
||||
src += unpack.RowLength * 4;
|
||||
src += srcStride;
|
||||
destY += yStep;
|
||||
}
|
||||
}
|
||||
@@ -130,21 +129,25 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
|
||||
span.x = destX;
|
||||
span.y = destY + row;
|
||||
span.end = drawWidth;
|
||||
span.array->ChanType = rbType;
|
||||
_swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, src);
|
||||
src += unpack.RowLength * 4;
|
||||
src += srcStride;
|
||||
}
|
||||
span.array->ChanType = CHAN_TYPE;
|
||||
}
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
if (format == GL_RGB && type == CHAN_TYPE && rbType == CHAN_TYPE) {
|
||||
const GLchan *src = (const GLchan *) pixels
|
||||
+ (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels) * 3;
|
||||
if (format == GL_RGB && type == rbType) {
|
||||
const GLubyte *src = _mesa_image_address2d(&unpack, pixels, width,
|
||||
height, format, type, 0, 0);
|
||||
const GLint srcStride = _mesa_image_row_stride(&unpack, width,
|
||||
format, type);
|
||||
if (simpleZoom) {
|
||||
GLint row;
|
||||
for (row = 0; row < drawHeight; row++) {
|
||||
rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL);
|
||||
src += unpack.RowLength * 3;
|
||||
src += srcStride;
|
||||
destY += yStep;
|
||||
}
|
||||
}
|
||||
@@ -155,14 +158,20 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
|
||||
span.x = destX;
|
||||
span.y = destY;
|
||||
span.end = drawWidth;
|
||||
span.array->ChanType = rbType;
|
||||
_swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, src);
|
||||
src += unpack.RowLength * 3;
|
||||
src += srcStride;
|
||||
destY++;
|
||||
}
|
||||
span.array->ChanType = CHAN_TYPE;
|
||||
}
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/* Remaining cases haven't been tested with alignment != 1 */
|
||||
if (userUnpack->Alignment != 1)
|
||||
return GL_FALSE;
|
||||
|
||||
if (format == GL_LUMINANCE && type == CHAN_TYPE && rbType == CHAN_TYPE) {
|
||||
const GLchan *src = (const GLchan *) pixels
|
||||
+ (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels);
|
||||
@@ -530,7 +539,7 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
|
||||
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
* Draw RGBA image.
|
||||
*/
|
||||
static void
|
||||
@@ -542,19 +551,17 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
const GLint imgX = x, imgY = y;
|
||||
struct gl_renderbuffer *rb = NULL; /* only used for quickDraw path */
|
||||
const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
|
||||
GLboolean quickDraw;
|
||||
GLfloat *convImage = NULL;
|
||||
GLuint transferOps = ctx->_ImageTransferState;
|
||||
SWspan span;
|
||||
|
||||
/* Try an optimized glDrawPixels first */
|
||||
if (fast_draw_pixels(ctx, x, y, width, height, format, type, unpack, pixels))
|
||||
if (fast_draw_rgba_pixels(ctx, x, y, width, height, format, type,
|
||||
unpack, pixels))
|
||||
return;
|
||||
|
||||
INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
|
||||
|
||||
if (ctx->Depth.Test)
|
||||
_swrast_span_default_z(ctx, &span);
|
||||
if (swrast->_FogEnabled)
|
||||
@@ -562,21 +569,6 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
|
||||
if (ctx->Texture._EnabledCoordUnits)
|
||||
_swrast_span_default_texcoords(ctx, &span);
|
||||
|
||||
if (swrast->_RasterMask == 0 && !zoom && x >= 0 && y >= 0
|
||||
&& x + width <= (GLint) ctx->DrawBuffer->Width
|
||||
&& y + height <= (GLint) ctx->DrawBuffer->Height
|
||||
&& ctx->DrawBuffer->_NumColorDrawBuffers[0] == 1) {
|
||||
rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
|
||||
if (rb->DataType == format)
|
||||
quickDraw = GL_TRUE;
|
||||
else
|
||||
quickDraw = GL_FALSE;
|
||||
}
|
||||
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
|
||||
@@ -628,6 +620,13 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
|
||||
transferOps &= IMAGE_POST_CONVOLUTION_BITS;
|
||||
}
|
||||
|
||||
if (ctx->DrawBuffer->_NumColorDrawBuffers[0] > 0 &&
|
||||
ctx->DrawBuffer->_ColorDrawBuffers[0][0]->DataType != GL_FLOAT &&
|
||||
ctx->Color.ClampFragmentColor != GL_FALSE) {
|
||||
/* need to clamp colors before applying fragment ops */
|
||||
transferOps |= IMAGE_CLAMP_BIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* General solution
|
||||
*/
|
||||
@@ -636,53 +635,51 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
|
||||
|| (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink);
|
||||
const GLbitfield interpMask = span.interpMask;
|
||||
const GLbitfield arrayMask = span.arrayMask;
|
||||
const GLint srcStride
|
||||
= _mesa_image_row_stride(unpack, width, format, type);
|
||||
GLint skipPixels = 0;
|
||||
/* use span array for temp color storage */
|
||||
GLfloat *rgba = (GLfloat *) span.array->color.sz4.rgba;
|
||||
|
||||
/* if the span is wider than MAX_WIDTH we have to do it in chunks */
|
||||
while (skipPixels < width) {
|
||||
const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
|
||||
const GLubyte *source = _mesa_image_address2d(unpack, pixels,
|
||||
width, height, format, type, 0, skipPixels);
|
||||
GLint row;
|
||||
|
||||
ASSERT(span.end <= MAX_WIDTH);
|
||||
|
||||
for (row = 0; row < height; row++) {
|
||||
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.
|
||||
/* get image row as float/RGBA */
|
||||
_mesa_unpack_color_span_float(ctx, spanWidth, GL_RGBA, rgba,
|
||||
format, type, source, unpack,
|
||||
transferOps);
|
||||
/* draw the span */
|
||||
if (!sink) {
|
||||
/* Set these for each row since the _swrast_write_* functions
|
||||
* may change them while clipping/rendering.
|
||||
*/
|
||||
span.array->ChanType = CHAN_TYPE;
|
||||
span.array->ChanType = GL_FLOAT;
|
||||
span.x = x + skipPixels;
|
||||
span.y = y + row;
|
||||
span.end = spanWidth;
|
||||
span.arrayMask = arrayMask;
|
||||
span.interpMask = interpMask;
|
||||
|
||||
_mesa_unpack_color_span_chan(ctx, spanWidth, GL_RGBA,
|
||||
(GLchan *) span.array->rgba,
|
||||
format, type, source, unpack,
|
||||
transferOps);
|
||||
|
||||
if (sink)
|
||||
continue;
|
||||
|
||||
/* 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, imgX, imgY, &span,
|
||||
span.array->rgba);
|
||||
if (zoom) {
|
||||
_swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba);
|
||||
}
|
||||
else {
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
}
|
||||
}
|
||||
|
||||
source += srcStride;
|
||||
} /* for row */
|
||||
|
||||
skipPixels += spanWidth;
|
||||
}
|
||||
} /* while skipPixels < width */
|
||||
|
||||
/* XXX this is ugly/temporary, to undo above change */
|
||||
span.array->ChanType = CHAN_TYPE;
|
||||
}
|
||||
|
||||
if (convImage) {
|
||||
|
@@ -54,7 +54,7 @@ _swrast_CopyColorTable( GLcontext *ctx,
|
||||
|
||||
/* read the data from framebuffer */
|
||||
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
|
||||
width, x, y, data );
|
||||
width, x, y, CHAN_TYPE, data );
|
||||
|
||||
RENDER_FINISH(swrast,ctx);
|
||||
|
||||
@@ -89,7 +89,7 @@ _swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start,
|
||||
|
||||
/* read the data from framebuffer */
|
||||
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
|
||||
width, x, y, data );
|
||||
width, x, y, CHAN_TYPE, data );
|
||||
|
||||
RENDER_FINISH(swrast,ctx);
|
||||
|
||||
@@ -122,7 +122,7 @@ _swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
|
||||
|
||||
/* read the data from framebuffer */
|
||||
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
|
||||
width, x, y, (GLchan (*)[4]) rgba );
|
||||
width, x, y, CHAN_TYPE, rgba );
|
||||
|
||||
RENDER_FINISH( swrast, ctx );
|
||||
|
||||
@@ -160,7 +160,7 @@ _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
|
||||
/* read pixels from framebuffer */
|
||||
for (i = 0; i < height; i++) {
|
||||
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
|
||||
width, x, y + i, (GLchan (*)[4]) rgba[i] );
|
||||
width, x, y + i, CHAN_TYPE, rgba[i] );
|
||||
}
|
||||
|
||||
RENDER_FINISH(swrast,ctx);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 6.5
|
||||
* Version: 6.5.2
|
||||
*
|
||||
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
|
||||
*
|
||||
@@ -197,7 +197,7 @@ read_stencil_pixels( GLcontext *ctx,
|
||||
* scaling, biasing, mapping, etc. are disabled.
|
||||
*/
|
||||
static GLboolean
|
||||
read_fast_rgba_pixels( GLcontext *ctx,
|
||||
fast_read_rgba_pixels( GLcontext *ctx,
|
||||
GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
@@ -206,53 +206,59 @@ read_fast_rgba_pixels( GLcontext *ctx,
|
||||
{
|
||||
struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
|
||||
|
||||
ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
|
||||
|
||||
/* clipping should have already been done */
|
||||
ASSERT(x + width <= rb->Width);
|
||||
ASSERT(y + height <= rb->Height);
|
||||
|
||||
/* can't do scale, bias, mapping, etc */
|
||||
if (ctx->_ImageTransferState)
|
||||
/* check for things we can't handle here */
|
||||
if (ctx->_ImageTransferState ||
|
||||
packing->SwapBytes ||
|
||||
packing->LsbFirst) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* can't do fancy pixel packing */
|
||||
if (packing->Alignment != 1 || packing->SwapBytes || packing->LsbFirst)
|
||||
return GL_FALSE;
|
||||
|
||||
/* if the pixel format exactly matches the renderbuffer format */
|
||||
if (format == GL_RGBA && rb->DataType == type) {
|
||||
GLint rowLength = (packing->RowLength > 0) ? packing->RowLength : width;
|
||||
GLint pixelSize, row;
|
||||
GLubyte *dest;
|
||||
|
||||
if (type == GL_UNSIGNED_BYTE)
|
||||
pixelSize = 4 * sizeof(GLubyte);
|
||||
else if (type == GL_UNSIGNED_SHORT)
|
||||
pixelSize = 4 * sizeof(GLushort);
|
||||
else {
|
||||
ASSERT(type == GL_FLOAT);
|
||||
pixelSize = 4 * sizeof(GLfloat);
|
||||
}
|
||||
|
||||
dest = (GLubyte *) pixels
|
||||
+ (packing->SkipRows * rowLength + packing->SkipPixels) * pixelSize;
|
||||
|
||||
if (packing->Invert) {
|
||||
/* start at top and go down */
|
||||
dest += (height - 1) * rowLength * pixelSize;
|
||||
rowLength = -rowLength;
|
||||
}
|
||||
|
||||
const GLint dstStride = _mesa_image_row_stride(packing, width,
|
||||
format, type);
|
||||
GLubyte *dest = _mesa_image_address2d(packing, pixels, width, height,
|
||||
format, type, 0, 0);
|
||||
GLint row;
|
||||
ASSERT(rb->GetRow);
|
||||
for (row = 0; row < height; row++) {
|
||||
rb->GetRow(ctx, rb, width, x, y + row, dest);
|
||||
dest += rowLength * pixelSize;
|
||||
dest += dstStride;
|
||||
}
|
||||
return GL_TRUE;
|
||||
}
|
||||
else {
|
||||
/* can't do this format/type combination */
|
||||
return GL_FALSE;
|
||||
|
||||
if (format == GL_RGB &&
|
||||
rb->DataType == GL_UNSIGNED_BYTE &&
|
||||
type == GL_UNSIGNED_BYTE) {
|
||||
const GLint dstStride = _mesa_image_row_stride(packing, width,
|
||||
format, type);
|
||||
GLubyte *dest = _mesa_image_address2d(packing, pixels, width, height,
|
||||
format, type, 0, 0);
|
||||
GLint row;
|
||||
ASSERT(rb->GetRow);
|
||||
for (row = 0; row < height; row++) {
|
||||
GLubyte tempRow[MAX_WIDTH][4];
|
||||
GLint col;
|
||||
rb->GetRow(ctx, rb, width, x, y + row, tempRow);
|
||||
/* convert RGBA to RGB */
|
||||
for (col = 0; col < width; col++) {
|
||||
dest[col * 3 + 0] = tempRow[col][0];
|
||||
dest[col * 3 + 1] = tempRow[col][1];
|
||||
dest[col * 3 + 2] = tempRow[col][2];
|
||||
}
|
||||
dest += dstStride;
|
||||
}
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/* not handled */
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -267,13 +273,14 @@ read_rgba_pixels( GLcontext *ctx,
|
||||
GLenum format, GLenum type, GLvoid *pixels,
|
||||
const struct gl_pixelstore_attrib *packing )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
struct gl_framebuffer *fb = ctx->ReadBuffer;
|
||||
struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
|
||||
|
||||
ASSERT(rb);
|
||||
|
||||
/* Try optimized path first */
|
||||
if (read_fast_rgba_pixels( ctx, x, y, width, height,
|
||||
if (fast_read_rgba_pixels(ctx, x, y, width, height,
|
||||
format, type, pixels, packing)) {
|
||||
return; /* done! */
|
||||
}
|
||||
@@ -301,9 +308,8 @@ read_rgba_pixels( GLcontext *ctx,
|
||||
/* read full RGBA, FLOAT image */
|
||||
dest = tmpImage;
|
||||
for (row = 0; row < height; row++, y++) {
|
||||
GLchan rgba[MAX_WIDTH][4];
|
||||
if (fb->Visual.rgbMode) {
|
||||
_swrast_read_rgba_span(ctx, rb, width, x, y, rgba);
|
||||
_swrast_read_rgba_span(ctx, rb, width, x, y, GL_FLOAT, dest);
|
||||
}
|
||||
else {
|
||||
GLuint index[MAX_WIDTH];
|
||||
@@ -312,11 +318,11 @@ read_rgba_pixels( GLcontext *ctx,
|
||||
if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset !=0 ) {
|
||||
_mesa_map_ci(ctx, width, index);
|
||||
}
|
||||
_mesa_map_ci_to_rgba_chan(ctx, width, index, rgba);
|
||||
_mesa_map_ci_to_rgba(ctx, width, index, (GLfloat (*)[4]) dest);
|
||||
}
|
||||
_mesa_pack_rgba_span_chan(ctx, width, (const GLchan (*)[4]) rgba,
|
||||
GL_RGBA, GL_FLOAT, dest, &ctx->DefaultPacking,
|
||||
transferOps & IMAGE_PRE_CONVOLUTION_BITS);
|
||||
_mesa_apply_rgba_transfer_ops(ctx,
|
||||
transferOps & IMAGE_PRE_CONVOLUTION_BITS,
|
||||
width, (GLfloat (*)[4]) dest);
|
||||
dest += width * 4;
|
||||
}
|
||||
|
||||
@@ -346,24 +352,35 @@ read_rgba_pixels( GLcontext *ctx,
|
||||
}
|
||||
else {
|
||||
/* no convolution */
|
||||
const GLint dstStride
|
||||
= _mesa_image_row_stride(packing, width, format, type);
|
||||
GLfloat (*rgba)[4] = swrast->SpanArrays->color.sz4.rgba;
|
||||
GLint row;
|
||||
GLubyte *dst = _mesa_image_address2d(packing, pixels, width, height,
|
||||
format, type, 0, 0);
|
||||
|
||||
for (row = 0; row < height; row++, y++) {
|
||||
GLchan rgba[MAX_WIDTH][4];
|
||||
GLvoid *dst;
|
||||
|
||||
/* Get float rgba pixels */
|
||||
if (fb->Visual.rgbMode) {
|
||||
_swrast_read_rgba_span(ctx, rb, width, x, y, rgba);
|
||||
_swrast_read_rgba_span(ctx, rb, width, x, y, GL_FLOAT, rgba);
|
||||
}
|
||||
else {
|
||||
/* read CI and convert to RGBA */
|
||||
GLuint index[MAX_WIDTH];
|
||||
ASSERT(rb->DataType == GL_UNSIGNED_INT);
|
||||
rb->GetRow(ctx, rb, width, x, y, index);
|
||||
if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset != 0) {
|
||||
_mesa_map_ci(ctx, width, index);
|
||||
}
|
||||
_mesa_map_ci_to_rgba_chan(ctx, width, index, rgba);
|
||||
_mesa_map_ci_to_rgba(ctx, width, index, rgba);
|
||||
}
|
||||
dst = _mesa_image_address2d(packing, pixels, width, height,
|
||||
format, type, row, 0);
|
||||
|
||||
/* pack the row of RGBA pixels into user's buffer */
|
||||
#if 0
|
||||
/* XXX may need to rejuvinate this code if we get conformance
|
||||
* falures on 16bpp displays (i.e. 5/6/5).
|
||||
*/
|
||||
if (fb->Visual.redBits < CHAN_BITS ||
|
||||
fb->Visual.greenBits < CHAN_BITS ||
|
||||
fb->Visual.blueBits < CHAN_BITS) {
|
||||
@@ -379,12 +396,15 @@ read_rgba_pixels( GLcontext *ctx,
|
||||
format, type, dst, packing,
|
||||
ctx->_ImageTransferState);
|
||||
}
|
||||
else {
|
||||
/* GLubytes are fine */
|
||||
_mesa_pack_rgba_span_chan(ctx, width, (CONST GLchan (*)[4]) rgba,
|
||||
format, type, dst, packing,
|
||||
ctx->_ImageTransferState);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_mesa_pack_rgba_span_float(ctx, width, (CONST GLfloat (*)[4]) rgba,
|
||||
format, type, dst,
|
||||
packing, ctx->_ImageTransferState);
|
||||
}
|
||||
|
||||
dst += dstStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1560,14 +1560,16 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Read RGBA pixels from frame buffer. Clipping will be done to prevent
|
||||
* reading ouside the buffer's boundaries.
|
||||
* \param type datatype for returned colors
|
||||
* \param rgba the returned colors
|
||||
*/
|
||||
void
|
||||
_swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
|
||||
GLuint n, GLint x, GLint y, GLchan rgba[][4] )
|
||||
GLuint n, GLint x, GLint y, GLenum dstType,
|
||||
GLvoid *rgba)
|
||||
{
|
||||
const GLint bufWidth = (GLint) rb->Width;
|
||||
const GLint bufHeight = (GLint) rb->Height;
|
||||
@@ -1609,8 +1611,18 @@ _swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
|
||||
ASSERT(rb);
|
||||
ASSERT(rb->GetRow);
|
||||
ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
|
||||
ASSERT(rb->DataType == CHAN_TYPE);
|
||||
rb->GetRow(ctx, rb, length, x + skip, y, rgba + skip);
|
||||
|
||||
if (rb->DataType == dstType) {
|
||||
rb->GetRow(ctx, rb, length, x + skip, y,
|
||||
(GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
|
||||
}
|
||||
else {
|
||||
GLuint temp[MAX_WIDTH * 4];
|
||||
rb->GetRow(ctx, rb, length, x + skip, y, temp);
|
||||
_mesa_convert_colors(rb->DataType, temp,
|
||||
dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType),
|
||||
length, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1801,7 +1813,7 @@ void *
|
||||
_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
|
||||
SWspan *span)
|
||||
{
|
||||
GLuint pixelSize;
|
||||
const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
|
||||
void *rbPixels;
|
||||
|
||||
/*
|
||||
@@ -1809,15 +1821,12 @@ _swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
|
||||
* Point rbPixels to a temporary space (use specular color arrays).
|
||||
*/
|
||||
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
|
||||
pixelSize = 4 * sizeof(GLubyte);
|
||||
rbPixels = span->array->color.sz1.spec;
|
||||
}
|
||||
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
|
||||
pixelSize = 4 * sizeof(GLushort);
|
||||
rbPixels = span->array->color.sz2.spec;
|
||||
}
|
||||
else {
|
||||
pixelSize = 4 * sizeof(GLfloat);
|
||||
rbPixels = span->array->color.sz4.spec;
|
||||
}
|
||||
|
||||
|
@@ -61,7 +61,7 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span);
|
||||
|
||||
extern void
|
||||
_swrast_read_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
|
||||
GLuint n, GLint x, GLint y, GLchan rgba[][4] );
|
||||
GLuint n, GLint x, GLint y, GLenum type, GLvoid *rgba);
|
||||
|
||||
extern void
|
||||
_swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 6.5.1
|
||||
* Version: 6.5.2
|
||||
*
|
||||
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
|
||||
*
|
||||
@@ -52,33 +52,37 @@
|
||||
#include "s_depth.h"
|
||||
#include "s_span.h"
|
||||
|
||||
/*
|
||||
|
||||
/**
|
||||
* Read an RGBA image from the frame buffer.
|
||||
* This is used by glCopyTex[Sub]Image[12]D().
|
||||
* Input: ctx - the context
|
||||
* x, y - lower left corner
|
||||
* width, height - size of region to read
|
||||
* Return: pointer to block of GL_RGBA, GLchan data.
|
||||
* \param x window source x
|
||||
* \param y window source y
|
||||
* \param width image width
|
||||
* \param height image height
|
||||
* \param type datatype for returned GL_RGBA image
|
||||
* \return pointer to image
|
||||
*/
|
||||
static GLchan *
|
||||
read_color_image( GLcontext *ctx, GLint x, GLint y,
|
||||
static GLvoid *
|
||||
read_color_image( GLcontext *ctx, GLint x, GLint y, GLenum type,
|
||||
GLsizei width, GLsizei height )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
const GLint stride = 4 * width;
|
||||
GLint i;
|
||||
GLchan *image, *dst;
|
||||
struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
|
||||
const GLint pixelSize = _mesa_bytes_per_pixel(GL_RGBA, type);
|
||||
const GLint stride = width * pixelSize;
|
||||
GLint row;
|
||||
GLubyte *image, *dst;
|
||||
|
||||
image = (GLchan *) _mesa_malloc(width * height * 4 * sizeof(GLchan));
|
||||
image = (GLubyte *) _mesa_malloc(width * height * pixelSize);
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
RENDER_START(swrast, ctx);
|
||||
|
||||
dst = image;
|
||||
for (i = 0; i < height; i++) {
|
||||
_swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer,
|
||||
width, x, y + i, (GLchan (*)[4]) dst);
|
||||
for (row = 0; row < height; row++) {
|
||||
_swrast_read_rgba_span(ctx, rb, width, x, y + row, type, dst);
|
||||
dst += stride;
|
||||
}
|
||||
|
||||
@@ -285,15 +289,16 @@ _swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level,
|
||||
}
|
||||
else {
|
||||
/* read RGBA image from framebuffer */
|
||||
GLchan *image = read_color_image(ctx, x, y, width, 1);
|
||||
const GLenum format = GL_RGBA;
|
||||
const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
|
||||
GLvoid *image = read_color_image(ctx, x, y, type, width, 1);
|
||||
if (!image) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
|
||||
return;
|
||||
}
|
||||
/* call glTexImage1D to redefine the texture */
|
||||
ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
|
||||
width, border,
|
||||
GL_RGBA, CHAN_TYPE, image,
|
||||
width, border, format, type, image,
|
||||
&ctx->DefaultPacking, texObj, texImage);
|
||||
_mesa_free(image);
|
||||
}
|
||||
@@ -360,15 +365,16 @@ _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level,
|
||||
}
|
||||
else {
|
||||
/* read RGBA image from framebuffer */
|
||||
GLchan *image = read_color_image(ctx, x, y, width, height);
|
||||
const GLenum format = GL_RGBA;
|
||||
const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
|
||||
GLvoid *image = read_color_image(ctx, x, y, type, width, height);
|
||||
if (!image) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
|
||||
return;
|
||||
}
|
||||
/* call glTexImage2D to redefine the texture */
|
||||
ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
|
||||
width, height, border,
|
||||
GL_RGBA, CHAN_TYPE, image,
|
||||
width, height, border, format, type, image,
|
||||
&ctx->DefaultPacking, texObj, texImage);
|
||||
_mesa_free(image);
|
||||
}
|
||||
@@ -428,14 +434,16 @@ _swrast_copy_texsubimage1d( GLcontext *ctx, GLenum target, GLint level,
|
||||
}
|
||||
else {
|
||||
/* read RGBA image from framebuffer */
|
||||
GLchan *image = read_color_image(ctx, x, y, width, 1);
|
||||
const GLenum format = GL_RGBA;
|
||||
const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
|
||||
GLvoid *image = read_color_image(ctx, x, y, type, width, 1);
|
||||
if (!image) {
|
||||
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" );
|
||||
return;
|
||||
}
|
||||
/* now call glTexSubImage1D to do the real work */
|
||||
ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width,
|
||||
GL_RGBA, CHAN_TYPE, image,
|
||||
format, type, image,
|
||||
&ctx->DefaultPacking, texObj, texImage);
|
||||
_mesa_free(image);
|
||||
}
|
||||
@@ -501,7 +509,9 @@ _swrast_copy_texsubimage2d( GLcontext *ctx,
|
||||
}
|
||||
else {
|
||||
/* read RGBA image from framebuffer */
|
||||
GLchan *image = read_color_image(ctx, x, y, width, height);
|
||||
const GLenum format = GL_RGBA;
|
||||
const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
|
||||
GLvoid *image = read_color_image(ctx, x, y, type, width, height);
|
||||
if (!image) {
|
||||
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
|
||||
return;
|
||||
@@ -509,7 +519,7 @@ _swrast_copy_texsubimage2d( GLcontext *ctx,
|
||||
/* now call glTexSubImage2D to do the real work */
|
||||
ctx->Driver.TexSubImage2D(ctx, target, level,
|
||||
xoffset, yoffset, width, height,
|
||||
GL_RGBA, CHAN_TYPE, image,
|
||||
format, type, image,
|
||||
&ctx->DefaultPacking, texObj, texImage);
|
||||
_mesa_free(image);
|
||||
}
|
||||
@@ -572,7 +582,9 @@ _swrast_copy_texsubimage3d( GLcontext *ctx,
|
||||
}
|
||||
else {
|
||||
/* read RGBA image from framebuffer */
|
||||
GLchan *image = read_color_image(ctx, x, y, width, height);
|
||||
const GLenum format = GL_RGBA;
|
||||
const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
|
||||
GLvoid *image = read_color_image(ctx, x, y, type, width, height);
|
||||
if (!image) {
|
||||
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" );
|
||||
return;
|
||||
@@ -580,7 +592,7 @@ _swrast_copy_texsubimage3d( GLcontext *ctx,
|
||||
/* now call glTexSubImage3D to do the real work */
|
||||
ctx->Driver.TexSubImage3D(ctx, target, level,
|
||||
xoffset, yoffset, zoffset, width, height, 1,
|
||||
GL_RGBA, CHAN_TYPE, image,
|
||||
format, type, image,
|
||||
&ctx->DefaultPacking, texObj, texImage);
|
||||
_mesa_free(image);
|
||||
}
|
||||
|
Reference in New Issue
Block a user