gallium: create drawing surfaces as GPU_READ/WRITE only

Create different temporary surfaces for CPU_READ/WRITE when needed (such as
for glReadPixels, glAccum, some glCopy/DrawPixels, glCopyTexSubImage, etc).
This commit is contained in:
Brian Paul 2008-05-06 13:47:41 -06:00
parent 973d0c014d
commit 296378b6c8
6 changed files with 129 additions and 49 deletions

View File

@ -105,7 +105,7 @@ void
st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
{ {
struct st_renderbuffer *acc_strb = st_renderbuffer(rb); struct st_renderbuffer *acc_strb = st_renderbuffer(rb);
struct pipe_surface *acc_ps = acc_strb->surface; struct pipe_surface *acc_ps;
struct pipe_screen *screen = ctx->st->pipe->screen; struct pipe_screen *screen = ctx->st->pipe->screen;
const GLint xpos = ctx->DrawBuffer->_Xmin; const GLint xpos = ctx->DrawBuffer->_Xmin;
const GLint ypos = ctx->DrawBuffer->_Ymin; const GLint ypos = ctx->DrawBuffer->_Ymin;
@ -113,6 +113,8 @@ st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
const GLint height = ctx->DrawBuffer->_Ymax - ypos; const GLint height = ctx->DrawBuffer->_Ymax - ypos;
GLvoid *map; GLvoid *map;
acc_ps = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_WRITE);
map = screen->surface_map(screen, acc_ps, map = screen->surface_map(screen, acc_ps,
PIPE_BUFFER_USAGE_CPU_WRITE); PIPE_BUFFER_USAGE_CPU_WRITE);
@ -143,6 +145,7 @@ st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
} }
screen->surface_unmap(screen, acc_ps); screen->surface_unmap(screen, acc_ps);
pipe_surface_reference(&acc_ps, NULL);
} }
@ -185,70 +188,100 @@ accum_mad(GLcontext *ctx, GLfloat scale, GLfloat bias,
static void static void
accum_accum(struct pipe_context *pipe, GLfloat value, accum_accum(struct pipe_context *pipe, GLfloat value,
GLint xpos, GLint ypos, GLint width, GLint height, GLint xpos, GLint ypos, GLint width, GLint height,
struct pipe_surface *acc_ps, struct st_renderbuffer *acc_strb,
struct pipe_surface *color_ps) struct st_renderbuffer *color_strb)
{ {
struct pipe_screen *screen = pipe->screen;
struct pipe_surface *acc_surf, *color_surf;
GLfloat *colorBuf, *accBuf; GLfloat *colorBuf, *accBuf;
GLint i; GLint i;
acc_surf = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0,
(PIPE_BUFFER_USAGE_CPU_WRITE |
PIPE_BUFFER_USAGE_CPU_READ));
color_surf = screen->get_tex_surface(screen, color_strb->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_READ);
colorBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); colorBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
accBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); accBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
pipe_get_tile_rgba(pipe, color_ps, xpos, ypos, width, height, colorBuf); pipe_get_tile_rgba(pipe, color_surf, xpos, ypos, width, height, colorBuf);
acc_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf); acc_get_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, accBuf);
for (i = 0; i < 4 * width * height; i++) { for (i = 0; i < 4 * width * height; i++) {
accBuf[i] = accBuf[i] + colorBuf[i] * value; accBuf[i] = accBuf[i] + colorBuf[i] * value;
} }
acc_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf); acc_put_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, accBuf);
free(colorBuf); free(colorBuf);
free(accBuf); free(accBuf);
pipe_surface_reference(&acc_surf, NULL);
pipe_surface_reference(&color_surf, NULL);
} }
static void static void
accum_load(struct pipe_context *pipe, GLfloat value, accum_load(struct pipe_context *pipe, GLfloat value,
GLint xpos, GLint ypos, GLint width, GLint height, GLint xpos, GLint ypos, GLint width, GLint height,
struct pipe_surface *acc_ps, struct st_renderbuffer *acc_strb,
struct pipe_surface *color_ps) struct st_renderbuffer *color_strb)
{ {
struct pipe_screen *screen = pipe->screen;
struct pipe_surface *acc_surf, *color_surf;
GLfloat *buf; GLfloat *buf;
GLint i; GLint i;
acc_surf = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_WRITE);
color_surf = screen->get_tex_surface(screen, color_strb->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_READ);
buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
pipe_get_tile_rgba(pipe, color_ps, xpos, ypos, width, height, buf); pipe_get_tile_rgba(pipe, color_surf, xpos, ypos, width, height, buf);
for (i = 0; i < 4 * width * height; i++) { for (i = 0; i < 4 * width * height; i++) {
buf[i] = buf[i] * value; buf[i] = buf[i] * value;
} }
acc_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, buf); acc_put_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, buf);
free(buf); free(buf);
pipe_surface_reference(&acc_surf, NULL);
pipe_surface_reference(&color_surf, NULL);
} }
static void static void
accum_return(GLcontext *ctx, GLfloat value, accum_return(GLcontext *ctx, GLfloat value,
GLint xpos, GLint ypos, GLint width, GLint height, GLint xpos, GLint ypos, GLint width, GLint height,
struct pipe_surface *acc_ps, struct st_renderbuffer *acc_strb,
struct pipe_surface *color_ps) struct st_renderbuffer *color_strb)
{ {
struct pipe_context *pipe = ctx->st->pipe; struct pipe_context *pipe = ctx->st->pipe;
struct pipe_screen *screen = pipe->screen;
const GLubyte *colormask = ctx->Color.ColorMask; const GLubyte *colormask = ctx->Color.ColorMask;
struct pipe_surface *acc_surf, *color_surf;
GLfloat *abuf, *cbuf = NULL; GLfloat *abuf, *cbuf = NULL;
GLint i, ch; GLint i, ch;
abuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); abuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
acc_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, abuf); acc_surf = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_READ);
color_surf = screen->get_tex_surface(screen, color_strb->texture, 0, 0, 0,
(PIPE_BUFFER_USAGE_CPU_READ |
PIPE_BUFFER_USAGE_CPU_WRITE));
acc_get_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, abuf);
if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) { if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) {
cbuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); cbuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
pipe_get_tile_rgba(pipe, color_ps, xpos, ypos, width, height, cbuf); pipe_get_tile_rgba(pipe, color_surf, xpos, ypos, width, height, cbuf);
} }
for (i = 0; i < width * height; i++) { for (i = 0; i < width * height; i++) {
@ -263,11 +296,13 @@ accum_return(GLcontext *ctx, GLfloat value,
} }
} }
pipe_put_tile_rgba(pipe, color_ps, xpos, ypos, width, height, abuf); pipe_put_tile_rgba(pipe, color_surf, xpos, ypos, width, height, abuf);
free(abuf); free(abuf);
if (cbuf) if (cbuf)
free(cbuf); free(cbuf);
pipe_surface_reference(&acc_surf, NULL);
pipe_surface_reference(&color_surf, NULL);
} }
@ -280,8 +315,6 @@ st_Accum(GLcontext *ctx, GLenum op, GLfloat value)
= st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); = st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
struct st_renderbuffer *color_strb struct st_renderbuffer *color_strb
= st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
struct pipe_surface *acc_ps = acc_strb->surface;
struct pipe_surface *color_ps = color_strb->surface;
const GLint xpos = ctx->DrawBuffer->_Xmin; const GLint xpos = ctx->DrawBuffer->_Xmin;
const GLint ypos = ctx->DrawBuffer->_Ymin; const GLint ypos = ctx->DrawBuffer->_Ymin;
@ -304,14 +337,14 @@ st_Accum(GLcontext *ctx, GLenum op, GLfloat value)
break; break;
case GL_ACCUM: case GL_ACCUM:
if (value != 0.0F) { if (value != 0.0F) {
accum_accum(pipe, value, xpos, ypos, width, height, acc_ps, color_ps); accum_accum(pipe, value, xpos, ypos, width, height, acc_strb, color_strb);
} }
break; break;
case GL_LOAD: case GL_LOAD:
accum_load(pipe, value, xpos, ypos, width, height, acc_ps, color_ps); accum_load(pipe, value, xpos, ypos, width, height, acc_strb, color_strb);
break; break;
case GL_RETURN: case GL_RETURN:
accum_return(ctx, value, xpos, ypos, width, height, acc_ps, color_ps); accum_return(ctx, value, xpos, ypos, width, height, acc_strb, color_strb);
break; break;
default: default:
assert(0); assert(0);

View File

@ -734,13 +734,19 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
struct st_context *st = ctx->st; struct st_context *st = ctx->st;
struct pipe_context *pipe = st->pipe; struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen; struct pipe_screen *screen = pipe->screen;
struct pipe_surface *ps = st->state.framebuffer.zsbuf; struct st_renderbuffer *strb;
struct pipe_surface *ps;
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
GLint skipPixels; GLint skipPixels;
ubyte *stmap; ubyte *stmap;
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
strb = st_renderbuffer(ctx->DrawBuffer->
Attachment[BUFFER_STENCIL].Renderbuffer);
ps = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_WRITE);
/* map the stencil buffer */ /* map the stencil buffer */
stmap = screen->surface_map(screen, ps, stmap = screen->surface_map(screen, ps,
PIPE_BUFFER_USAGE_CPU_WRITE); PIPE_BUFFER_USAGE_CPU_WRITE);
@ -801,6 +807,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
/* unmap the stencil buffer */ /* unmap the stencil buffer */
screen->surface_unmap(screen, ps); screen->surface_unmap(screen, ps);
pipe_surface_reference(&ps, NULL);
} }
@ -874,7 +881,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
{ {
struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer); struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer);
struct pipe_screen *screen = ctx->st->pipe->screen; struct pipe_screen *screen = ctx->st->pipe->screen;
struct pipe_surface *psDraw = rbDraw->surface; struct pipe_surface *psDraw;
ubyte *drawMap; ubyte *drawMap;
ubyte *buffer; ubyte *buffer;
int i; int i;
@ -889,6 +896,9 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
st_read_stencil_pixels(ctx, srcx, srcy, width, height, GL_UNSIGNED_BYTE, st_read_stencil_pixels(ctx, srcx, srcy, width, height, GL_UNSIGNED_BYTE,
&ctx->DefaultPacking, buffer); &ctx->DefaultPacking, buffer);
psDraw = screen->get_tex_surface(screen, rbDraw->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_WRITE);
/* map the stencil buffer */ /* map the stencil buffer */
drawMap = screen->surface_map(screen, psDraw, PIPE_BUFFER_USAGE_CPU_WRITE); drawMap = screen->surface_map(screen, psDraw, PIPE_BUFFER_USAGE_CPU_WRITE);
@ -931,6 +941,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
/* unmap the stencil buffer */ /* unmap the stencil buffer */
screen->surface_unmap(screen, psDraw); screen->surface_unmap(screen, psDraw);
pipe_surface_reference(&psDraw, NULL);
} }
@ -945,7 +956,6 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
struct st_renderbuffer *rbRead; struct st_renderbuffer *rbRead;
struct st_vertex_program *stvp; struct st_vertex_program *stvp;
struct st_fragment_program *stfp; struct st_fragment_program *stfp;
struct pipe_surface *psRead;
struct pipe_surface *psTex; struct pipe_surface *psTex;
struct pipe_texture *pt; struct pipe_texture *pt;
GLfloat *color; GLfloat *color;
@ -976,8 +986,12 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE); stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
} }
#if 0
psRead = rbRead->surface; psRead = rbRead->surface;
srcFormat = psRead->format; srcFormat = psRead->format;
#else
srcFormat = rbRead->texture->format;
#endif
if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE)) { if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE)) {
texFormat = srcFormat; texFormat = srcFormat;
@ -1005,18 +1019,26 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
} }
if (srcFormat == texFormat) { if (srcFormat == texFormat) {
/* copy source framebuffer surface into mipmap/texture */
struct pipe_surface *psRead = screen->get_tex_surface(screen,
rbRead->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_READ);
psTex = screen->get_tex_surface(screen, pt, 0, 0, 0, psTex = screen->get_tex_surface(screen, pt, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_WRITE ); PIPE_BUFFER_USAGE_GPU_WRITE );
/* copy source framebuffer surface into mipmap/texture */
pipe->surface_copy(pipe, pipe->surface_copy(pipe,
FALSE, FALSE,
psTex, /* dest */ psTex, /* dest */
0, 0, /* destx/y */ 0, 0, /* destx/y */
psRead, psRead,
srcx, srcy, width, height); srcx, srcy, width, height);
pipe_surface_reference(&psRead, NULL);
} }
else { else {
/* CPU-based fallback/conversion */
struct pipe_surface *psRead = screen->get_tex_surface(screen,
rbRead->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_READ);
psTex = screen->get_tex_surface(screen, pt, 0, 0, 0, psTex = screen->get_tex_surface(screen, pt, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_WRITE ); PIPE_BUFFER_USAGE_CPU_WRITE );
@ -1036,6 +1058,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
pipe_put_tile_z(pipe, psTex, 0, 0, width, height, buf); pipe_put_tile_z(pipe, psTex, 0, 0, width, height, buf);
free(buf); free(buf);
} }
pipe_surface_reference(&psRead, NULL);
} }
pipe_surface_reference(&psTex, NULL); pipe_surface_reference(&psTex, NULL);

View File

@ -95,7 +95,7 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
{ {
struct pipe_context *pipe = ctx->st->pipe; struct pipe_context *pipe = ctx->st->pipe;
struct st_renderbuffer *strb = st_renderbuffer(rb); struct st_renderbuffer *strb = st_renderbuffer(rb);
struct pipe_texture template, *texture; struct pipe_texture template;
unsigned surface_usage; unsigned surface_usage;
/* Free the old surface (and texture if we hold the last /* Free the old surface (and texture if we hold the last
@ -136,12 +136,14 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
/* Probably need dedicated flags for surface usage too: /* Probably need dedicated flags for surface usage too:
*/ */
surface_usage = (PIPE_BUFFER_USAGE_GPU_READ | surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
PIPE_BUFFER_USAGE_GPU_WRITE | PIPE_BUFFER_USAGE_GPU_WRITE);
#if 0
PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_READ |
PIPE_BUFFER_USAGE_CPU_WRITE); PIPE_BUFFER_USAGE_CPU_WRITE);
#endif
texture = pipe->screen->texture_create( pipe->screen, strb->texture = pipe->screen->texture_create( pipe->screen,
&template ); &template );
/* Special path for accum buffers. /* Special path for accum buffers.
* *
@ -149,7 +151,7 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
* only for now, the surface pixel format doesn't really matter, * only for now, the surface pixel format doesn't really matter,
* only that the buffer is large enough. * only that the buffer is large enough.
*/ */
if (!texture && template.format == DEFAULT_ACCUM_PIPE_FORMAT) if (!strb->texture && template.format == DEFAULT_ACCUM_PIPE_FORMAT)
{ {
/* Actually, just setting this usage value should be sufficient /* Actually, just setting this usage value should be sufficient
* to tell the driver to go ahead and allocate the buffer, even * to tell the driver to go ahead and allocate the buffer, even
@ -159,21 +161,19 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
surface_usage = (PIPE_BUFFER_USAGE_CPU_READ | surface_usage = (PIPE_BUFFER_USAGE_CPU_READ |
PIPE_BUFFER_USAGE_CPU_WRITE); PIPE_BUFFER_USAGE_CPU_WRITE);
texture = pipe->screen->texture_create( pipe->screen, strb->texture = pipe->screen->texture_create( pipe->screen,
&template ); &template );
} }
if (!texture) if (!strb->texture)
return FALSE; return FALSE;
strb->surface = pipe->screen->get_tex_surface( pipe->screen, strb->surface = pipe->screen->get_tex_surface( pipe->screen,
texture, strb->texture,
0, 0, 0, 0, 0, 0,
surface_usage ); surface_usage );
pipe_texture_reference( &texture, NULL );
assert(strb->surface->buffer); assert(strb->surface->buffer);
assert(strb->surface->format); assert(strb->surface->format);
assert(strb->surface->cpp); assert(strb->surface->cpp);
@ -195,6 +195,7 @@ st_renderbuffer_delete(struct gl_renderbuffer *rb)
struct st_renderbuffer *strb = st_renderbuffer(rb); struct st_renderbuffer *strb = st_renderbuffer(rb);
ASSERT(strb); ASSERT(strb);
pipe_surface_reference(&strb->surface, NULL); pipe_surface_reference(&strb->surface, NULL);
pipe_texture_reference(&strb->texture, NULL);
free(strb); free(strb);
} }
@ -380,6 +381,8 @@ st_render_texture(GLcontext *ctx,
rb->Width = pt->width[att->TextureLevel]; rb->Width = pt->width[att->TextureLevel];
rb->Height = pt->height[att->TextureLevel]; rb->Height = pt->height[att->TextureLevel];
pipe_texture_reference( &strb->texture, pt );
/* the renderbuffer's surface is inside the texture */ /* the renderbuffer's surface is inside the texture */
strb->surface = screen->get_tex_surface(screen, pt, strb->surface = screen->get_tex_surface(screen, pt,
att->CubeMapFace, att->CubeMapFace,

View File

@ -41,7 +41,8 @@
struct st_renderbuffer struct st_renderbuffer
{ {
struct gl_renderbuffer Base; struct gl_renderbuffer Base;
struct pipe_surface *surface; struct pipe_texture *texture;
struct pipe_surface *surface; /* temporary view into texture */
enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */ enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */
}; };

View File

@ -63,10 +63,14 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
struct gl_framebuffer *fb = ctx->ReadBuffer; struct gl_framebuffer *fb = ctx->ReadBuffer;
struct pipe_screen *screen = ctx->st->pipe->screen; struct pipe_screen *screen = ctx->st->pipe->screen;
struct st_renderbuffer *strb = st_renderbuffer(fb->_StencilBuffer); struct st_renderbuffer *strb = st_renderbuffer(fb->_StencilBuffer);
struct pipe_surface *ps = strb->surface; struct pipe_surface *ps;
ubyte *stmap; ubyte *stmap;
GLint j; GLint j;
/* Create a CPU-READ surface/view into the renderbuffer's texture */
ps = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_READ);
/* map the stencil buffer */ /* map the stencil buffer */
stmap = screen->surface_map(screen, ps, PIPE_BUFFER_USAGE_CPU_READ); stmap = screen->surface_map(screen, ps, PIPE_BUFFER_USAGE_CPU_READ);
@ -126,6 +130,7 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
/* unmap the stencil buffer */ /* unmap the stencil buffer */
screen->surface_unmap(screen, ps); screen->surface_unmap(screen, ps);
pipe_surface_reference(&ps, NULL);
} }
@ -169,12 +174,14 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
GLvoid *dest) GLvoid *dest)
{ {
struct pipe_context *pipe = ctx->st->pipe; struct pipe_context *pipe = ctx->st->pipe;
struct pipe_screen *screen = pipe->screen;
GLfloat temp[MAX_WIDTH][4]; GLfloat temp[MAX_WIDTH][4];
const GLbitfield transferOps = ctx->_ImageTransferState; const GLbitfield transferOps = ctx->_ImageTransferState;
GLint i, yStep, dfStride; GLint i, yStep, dfStride;
GLfloat *df; GLfloat *df;
struct st_renderbuffer *strb; struct st_renderbuffer *strb;
struct gl_pixelstore_attrib clippedPacking = *pack; struct gl_pixelstore_attrib clippedPacking = *pack;
struct pipe_surface *surf;
/* XXX convolution not done yet */ /* XXX convolution not done yet */
assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0); assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0);
@ -230,6 +237,10 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
yStep = 1; yStep = 1;
} }
/* Create a CPU-READ surface/view into the renderbuffer's texture */
surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_READ);
/* /*
* Copy pixels from pipe_surface to user memory * Copy pixels from pipe_surface to user memory
*/ */
@ -241,15 +252,14 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width, const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width,
format, type); format, type);
if (strb->surface->format == PIPE_FORMAT_S8Z24_UNORM || if (surf->format == PIPE_FORMAT_S8Z24_UNORM ||
strb->surface->format == PIPE_FORMAT_X8Z24_UNORM) { surf->format == PIPE_FORMAT_X8Z24_UNORM) {
if (format == GL_DEPTH_COMPONENT) { if (format == GL_DEPTH_COMPONENT) {
for (i = 0; i < height; i++) { for (i = 0; i < height; i++) {
GLuint ztemp[MAX_WIDTH], j; GLuint ztemp[MAX_WIDTH], j;
GLfloat zfloat[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH];
const double scale = 1.0 / ((1 << 24) - 1); const double scale = 1.0 / ((1 << 24) - 1);
pipe_get_tile_raw(pipe, strb->surface, x, y, pipe_get_tile_raw(pipe, surf, x, y, width, 1, ztemp, 0);
width, 1, ztemp, 0);
y += yStep; y += yStep;
for (j = 0; j < width; j++) { for (j = 0; j < width; j++) {
zfloat[j] = (float) (scale * (ztemp[j] & 0xffffff)); zfloat[j] = (float) (scale * (ztemp[j] & 0xffffff));
@ -263,18 +273,18 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
/* untested, but simple: */ /* untested, but simple: */
assert(format == GL_DEPTH_STENCIL_EXT); assert(format == GL_DEPTH_STENCIL_EXT);
for (i = 0; i < height; i++) { for (i = 0; i < height; i++) {
pipe_get_tile_raw(pipe, strb->surface, x, y, width, 1, dst, 0); pipe_get_tile_raw(pipe, surf, x, y, width, 1, dst, 0);
y += yStep; y += yStep;
dst += dstStride; dst += dstStride;
} }
} }
} }
else if (strb->surface->format == PIPE_FORMAT_Z16_UNORM) { else if (surf->format == PIPE_FORMAT_Z16_UNORM) {
for (i = 0; i < height; i++) { for (i = 0; i < height; i++) {
GLushort ztemp[MAX_WIDTH], j; GLushort ztemp[MAX_WIDTH], j;
GLfloat zfloat[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH];
const double scale = 1.0 / 0xffff; const double scale = 1.0 / 0xffff;
pipe_get_tile_raw(pipe, strb->surface, x, y, width, 1, ztemp, 0); pipe_get_tile_raw(pipe, surf, x, y, width, 1, ztemp, 0);
y += yStep; y += yStep;
for (j = 0; j < width; j++) { for (j = 0; j < width; j++) {
zfloat[j] = (float) (scale * ztemp[j]); zfloat[j] = (float) (scale * ztemp[j]);
@ -284,12 +294,12 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
dst += dstStride; dst += dstStride;
} }
} }
else if (strb->surface->format == PIPE_FORMAT_Z32_UNORM) { else if (surf->format == PIPE_FORMAT_Z32_UNORM) {
for (i = 0; i < height; i++) { for (i = 0; i < height; i++) {
GLuint ztemp[MAX_WIDTH], j; GLuint ztemp[MAX_WIDTH], j;
GLfloat zfloat[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH];
const double scale = 1.0 / 0xffffffff; const double scale = 1.0 / 0xffffffff;
pipe_get_tile_raw(pipe, strb->surface, x, y, width, 1, ztemp, 0); pipe_get_tile_raw(pipe, surf, x, y, width, 1, ztemp, 0);
y += yStep; y += yStep;
for (j = 0; j < width; j++) { for (j = 0; j < width; j++) {
zfloat[j] = (float) (scale * ztemp[j]); zfloat[j] = (float) (scale * ztemp[j]);
@ -303,7 +313,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
/* RGBA format */ /* RGBA format */
/* Do a row at a time to flip image data vertically */ /* Do a row at a time to flip image data vertically */
for (i = 0; i < height; i++) { for (i = 0; i < height; i++) {
pipe_get_tile_rgba(pipe, strb->surface, x, y, width, 1, df); pipe_get_tile_rgba(pipe, surf, x, y, width, 1, df);
y += yStep; y += yStep;
df += dfStride; df += dfStride;
if (!dfStride) { if (!dfStride) {
@ -315,6 +325,8 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
} }
} }
pipe_surface_reference(&surf, NULL);
_mesa_unmap_readpix_pbo(ctx, &clippedPacking); _mesa_unmap_readpix_pbo(ctx, &clippedPacking);
} }

View File

@ -306,6 +306,11 @@ guess_and_alloc_texture(struct st_context *st,
depth <<= 1; depth <<= 1;
} }
if (width == 0 || height == 0 || depth == 0) {
/* no texture needed */
return;
}
/* Guess a reasonable value for lastLevel. This is probably going /* Guess a reasonable value for lastLevel. This is probably going
* to be wrong fairly often and might mean that we have to look at * to be wrong fairly often and might mean that we have to look at
* resizable buffers, or require that buffers implement lazy * resizable buffers, or require that buffers implement lazy
@ -1059,6 +1064,8 @@ fallback_copy_texsubimage(GLcontext *ctx,
} }
src_surf = strb->surface; src_surf = strb->surface;
src_surf = screen->get_tex_surface(screen, strb->texture, face, level, destZ,
PIPE_BUFFER_USAGE_CPU_READ);
dest_surf = screen->get_tex_surface(screen, pt, face, level, destZ, dest_surf = screen->get_tex_surface(screen, pt, face, level, destZ,
PIPE_BUFFER_USAGE_CPU_WRITE); PIPE_BUFFER_USAGE_CPU_WRITE);
@ -1097,6 +1104,7 @@ fallback_copy_texsubimage(GLcontext *ctx,
} }
screen->tex_surface_release(screen, &dest_surf); screen->tex_surface_release(screen, &dest_surf);
screen->tex_surface_release(screen, &src_surf);
} }
@ -1164,7 +1172,7 @@ do_copy_texsubimage(GLcontext *ctx,
stImage->level, destZ, stImage->level, destZ,
PIPE_BUFFER_USAGE_CPU_WRITE); PIPE_BUFFER_USAGE_CPU_WRITE);
if (ctx->_ImageTransferState == 0x0 && if (0&& ctx->_ImageTransferState == 0x0 &&
strb->surface->buffer && strb->surface->buffer &&
dest_surface->buffer) { dest_surface->buffer) {
/* do blit-style copy */ /* do blit-style copy */