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)
{
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;
const GLint xpos = ctx->DrawBuffer->_Xmin;
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;
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,
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);
pipe_surface_reference(&acc_ps, NULL);
}
@ -185,70 +188,100 @@ accum_mad(GLcontext *ctx, GLfloat scale, GLfloat bias,
static void
accum_accum(struct pipe_context *pipe, GLfloat value,
GLint xpos, GLint ypos, GLint width, GLint height,
struct pipe_surface *acc_ps,
struct pipe_surface *color_ps)
struct st_renderbuffer *acc_strb,
struct st_renderbuffer *color_strb)
{
struct pipe_screen *screen = pipe->screen;
struct pipe_surface *acc_surf, *color_surf;
GLfloat *colorBuf, *accBuf;
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));
accBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
pipe_get_tile_rgba(pipe, color_ps, xpos, ypos, width, height, colorBuf);
acc_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf);
pipe_get_tile_rgba(pipe, color_surf, xpos, ypos, width, height, colorBuf);
acc_get_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, accBuf);
for (i = 0; i < 4 * width * height; i++) {
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(accBuf);
pipe_surface_reference(&acc_surf, NULL);
pipe_surface_reference(&color_surf, NULL);
}
static void
accum_load(struct pipe_context *pipe, GLfloat value,
GLint xpos, GLint ypos, GLint width, GLint height,
struct pipe_surface *acc_ps,
struct pipe_surface *color_ps)
struct st_renderbuffer *acc_strb,
struct st_renderbuffer *color_strb)
{
struct pipe_screen *screen = pipe->screen;
struct pipe_surface *acc_surf, *color_surf;
GLfloat *buf;
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));
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++) {
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);
pipe_surface_reference(&acc_surf, NULL);
pipe_surface_reference(&color_surf, NULL);
}
static void
accum_return(GLcontext *ctx, GLfloat value,
GLint xpos, GLint ypos, GLint width, GLint height,
struct pipe_surface *acc_ps,
struct pipe_surface *color_ps)
struct st_renderbuffer *acc_strb,
struct st_renderbuffer *color_strb)
{
struct pipe_context *pipe = ctx->st->pipe;
struct pipe_screen *screen = pipe->screen;
const GLubyte *colormask = ctx->Color.ColorMask;
struct pipe_surface *acc_surf, *color_surf;
GLfloat *abuf, *cbuf = NULL;
GLint i, ch;
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]) {
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++) {
@ -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);
if (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);
struct st_renderbuffer *color_strb
= 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 ypos = ctx->DrawBuffer->_Ymin;
@ -304,14 +337,14 @@ st_Accum(GLcontext *ctx, GLenum op, GLfloat value)
break;
case GL_ACCUM:
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;
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;
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;
default:
assert(0);

View File

@ -734,13 +734,19 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
struct st_context *st = ctx->st;
struct pipe_context *pipe = st->pipe;
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;
GLint skipPixels;
ubyte *stmap;
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 */
stmap = screen->surface_map(screen, ps,
PIPE_BUFFER_USAGE_CPU_WRITE);
@ -801,6 +807,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
/* unmap the stencil buffer */
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 pipe_screen *screen = ctx->st->pipe->screen;
struct pipe_surface *psDraw = rbDraw->surface;
struct pipe_surface *psDraw;
ubyte *drawMap;
ubyte *buffer;
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,
&ctx->DefaultPacking, buffer);
psDraw = screen->get_tex_surface(screen, rbDraw->texture, 0, 0, 0,
PIPE_BUFFER_USAGE_CPU_WRITE);
/* map the stencil buffer */
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 */
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_vertex_program *stvp;
struct st_fragment_program *stfp;
struct pipe_surface *psRead;
struct pipe_surface *psTex;
struct pipe_texture *pt;
GLfloat *color;
@ -976,8 +986,12 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
}
#if 0
psRead = rbRead->surface;
srcFormat = psRead->format;
#else
srcFormat = rbRead->texture->format;
#endif
if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE)) {
texFormat = srcFormat;
@ -1005,18 +1019,26 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
}
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,
PIPE_BUFFER_USAGE_GPU_WRITE );
/* copy source framebuffer surface into mipmap/texture */
pipe->surface_copy(pipe,
FALSE,
psTex, /* dest */
0, 0, /* destx/y */
psRead,
srcx, srcy, width, height);
pipe_surface_reference(&psRead, NULL);
}
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,
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);
free(buf);
}
pipe_surface_reference(&psRead, 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 st_renderbuffer *strb = st_renderbuffer(rb);
struct pipe_texture template, *texture;
struct pipe_texture template;
unsigned surface_usage;
/* 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:
*/
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_WRITE);
#endif
texture = pipe->screen->texture_create( pipe->screen,
&template );
strb->texture = pipe->screen->texture_create( pipe->screen,
&template );
/* 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 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
* 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 |
PIPE_BUFFER_USAGE_CPU_WRITE);
texture = pipe->screen->texture_create( pipe->screen,
&template );
strb->texture = pipe->screen->texture_create( pipe->screen,
&template );
}
if (!texture)
if (!strb->texture)
return FALSE;
strb->surface = pipe->screen->get_tex_surface( pipe->screen,
texture,
strb->texture,
0, 0, 0,
surface_usage );
pipe_texture_reference( &texture, NULL );
assert(strb->surface->buffer);
assert(strb->surface->format);
assert(strb->surface->cpp);
@ -195,6 +195,7 @@ st_renderbuffer_delete(struct gl_renderbuffer *rb)
struct st_renderbuffer *strb = st_renderbuffer(rb);
ASSERT(strb);
pipe_surface_reference(&strb->surface, NULL);
pipe_texture_reference(&strb->texture, NULL);
free(strb);
}
@ -380,6 +381,8 @@ st_render_texture(GLcontext *ctx,
rb->Width = pt->width[att->TextureLevel];
rb->Height = pt->height[att->TextureLevel];
pipe_texture_reference( &strb->texture, pt );
/* the renderbuffer's surface is inside the texture */
strb->surface = screen->get_tex_surface(screen, pt,
att->CubeMapFace,

View File

@ -41,7 +41,8 @@
struct st_renderbuffer
{
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 */
};

View File

@ -63,10 +63,14 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
struct gl_framebuffer *fb = ctx->ReadBuffer;
struct pipe_screen *screen = ctx->st->pipe->screen;
struct st_renderbuffer *strb = st_renderbuffer(fb->_StencilBuffer);
struct pipe_surface *ps = strb->surface;
struct pipe_surface *ps;
ubyte *stmap;
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 */
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 */
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)
{
struct pipe_context *pipe = ctx->st->pipe;
struct pipe_screen *screen = pipe->screen;
GLfloat temp[MAX_WIDTH][4];
const GLbitfield transferOps = ctx->_ImageTransferState;
GLint i, yStep, dfStride;
GLfloat *df;
struct st_renderbuffer *strb;
struct gl_pixelstore_attrib clippedPacking = *pack;
struct pipe_surface *surf;
/* XXX convolution not done yet */
assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0);
@ -230,6 +237,10 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
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
*/
@ -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,
format, type);
if (strb->surface->format == PIPE_FORMAT_S8Z24_UNORM ||
strb->surface->format == PIPE_FORMAT_X8Z24_UNORM) {
if (surf->format == PIPE_FORMAT_S8Z24_UNORM ||
surf->format == PIPE_FORMAT_X8Z24_UNORM) {
if (format == GL_DEPTH_COMPONENT) {
for (i = 0; i < height; i++) {
GLuint ztemp[MAX_WIDTH], j;
GLfloat zfloat[MAX_WIDTH];
const double scale = 1.0 / ((1 << 24) - 1);
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;
for (j = 0; j < width; j++) {
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: */
assert(format == GL_DEPTH_STENCIL_EXT);
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;
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++) {
GLushort ztemp[MAX_WIDTH], j;
GLfloat zfloat[MAX_WIDTH];
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;
for (j = 0; j < width; 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;
}
}
else if (strb->surface->format == PIPE_FORMAT_Z32_UNORM) {
else if (surf->format == PIPE_FORMAT_Z32_UNORM) {
for (i = 0; i < height; i++) {
GLuint ztemp[MAX_WIDTH], j;
GLfloat zfloat[MAX_WIDTH];
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;
for (j = 0; j < width; 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 */
/* Do a row at a time to flip image data vertically */
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;
df += 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);
}

View File

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