gallium: create drawing surfaces as GPU_READ/WRITE only
authorBrian Paul <brian.paul@tungstengraphics.com>
Tue, 6 May 2008 19:47:41 +0000 (13:47 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Tue, 6 May 2008 19:48:27 +0000 (13:48 -0600)
Create different temporary surfaces for CPU_READ/WRITE when needed (such as
for glReadPixels, glAccum, some glCopy/DrawPixels, glCopyTexSubImage, etc).

src/mesa/state_tracker/st_cb_accum.c
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_cb_fbo.c
src/mesa/state_tracker/st_cb_fbo.h
src/mesa/state_tracker/st_cb_readpixels.c
src/mesa/state_tracker/st_cb_texture.c

index e4ef3e16b7d3777d5abfac05d034a87dfa379135..8098d75e18f337a78755f74bb9db78e92f5cda8e 100644 (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);
index 6ec3c343cdab0c6a9ee077b11786e34bc2dc53c8..c967c989de52a0e4a98992605c3d494e056274d5 100644 (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);
index e0578f0b4d7354929f77d51980b9fb4413bea1ea..747d4905e6b9a3d8460d754a2da1183f9c63e2ff 100644 (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,
index c1aa14f9b22ceeef99098c7ba5d13da6a7480b94..f9cec91314112f6f220f8849d854b34f1a9a1a54 100644 (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 */
 };
 
index e242195e7a94986958b72ac2ad36a3e2da43b7cd..0b2b9d544d79ac458e3f7ce4240e57ccde155bdd 100644 (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);
 }
 
index f6f833a0dbd824ab4848929543ea9b8da58be172..828b2340f22fb64c19733d1a01d3ff917657e1d9 100644 (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 */