Merge commit 'origin/master' into gallium-0.2
[mesa.git] / src / mesa / state_tracker / st_cb_drawpixels.c
index 43cc21d1fb4c58f6577ceb130c390deb13db0685..5b24b9f06874cf0c6eaeb63213f7511bf30f8bde 100644 (file)
@@ -35,6 +35,7 @@
 #include "main/bufferobj.h"
 #include "main/macros.h"
 #include "main/texformat.h"
+#include "main/state.h"
 #include "shader/program.h"
 #include "shader/prog_parameter.h"
 #include "shader/prog_print.h"
@@ -55,8 +56,7 @@
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_inlines.h"
-#include "pipe/p_winsys.h"
-#include "util/p_tile.h"
+#include "util/u_tile.h"
 #include "util/u_draw_quad.h"
 #include "shader/prog_instruction.h"
 #include "cso_cache/cso_context.h"
@@ -165,14 +165,16 @@ static struct st_fragment_program *
 make_fragment_shader_z(struct st_context *st)
 {
    GLcontext *ctx = st->ctx;
-   /* only make programs once and re-use */
-   static struct st_fragment_program *stfp = NULL;
    struct gl_program *p;
    GLuint ic = 0;
 
-   if (stfp)
-      return stfp;
+   if (st->drawpix.z_shader) {
+      return st->drawpix.z_shader;
+   }
 
+   /*
+    * Create shader now
+    */
    p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
    if (!p)
       return NULL;
@@ -212,11 +214,12 @@ make_fragment_shader_z(struct st_context *st)
 
    p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
    p->OutputsWritten = (1 << FRAG_RESULT_COLR) | (1 << FRAG_RESULT_DEPR);
+   p->SamplersUsed = 0x1;  /* sampler 0 (bit 0) is used */
 
-   stfp = (struct st_fragment_program *) p;
-   st_translate_fragment_program(st, stfp, NULL);
+   st->drawpix.z_shader = (struct st_fragment_program *) p;
+   st_translate_fragment_program(st, st->drawpix.z_shader, NULL);
 
-   return stfp;
+   return st->drawpix.z_shader;
 }
 
 
@@ -228,16 +231,17 @@ make_fragment_shader_z(struct st_context *st)
 static struct st_vertex_program *
 st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor)
 {
-   /* only make programs once and re-use */
-   static struct st_vertex_program *progs[2] = { NULL, NULL };
    GLcontext *ctx = st->ctx;
    struct st_vertex_program *stvp;
    struct gl_program *p;
    GLuint ic = 0;
 
-   if (progs[passColor])
-      return progs[passColor];
+   if (st->drawpix.vert_shaders[passColor])
+      return st->drawpix.vert_shaders[passColor];
 
+   /*
+    * Create shader now
+    */
    p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
    if (!p)
       return NULL;
@@ -291,9 +295,9 @@ st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor)
    }
 
    stvp = (struct st_vertex_program *) p;
-   st_translate_vertex_program(st, stvp, NULL);
+   st_translate_vertex_program(st, stvp, NULL, NULL, NULL);
 
-   progs[passColor] = stvp;
+   st->drawpix.vert_shaders[passColor] = stvp;
 
    return stvp;
 }
@@ -346,9 +350,10 @@ make_texture(struct st_context *st,
       return NULL;
 
    pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height,
-                         1, 0);
+                         1, 0,
+                          PIPE_TEXTURE_USAGE_SAMPLER);
    if (!pt) {
-      _mesa_unmap_drapix_pbo(ctx, unpack);
+      _mesa_unmap_drawpix_pbo(ctx, unpack);
       return NULL;
    }
 
@@ -362,10 +367,12 @@ make_texture(struct st_context *st,
       /* we'll do pixel transfer in a fragment shader */
       ctx->_ImageTransferState = 0x0;
 
-      surface = screen->get_tex_surface(screen, pt, 0, 0, 0);
+      surface = screen->get_tex_surface(screen, pt, 0, 0, 0,
+                                        PIPE_BUFFER_USAGE_CPU_WRITE);
 
       /* map texture surface */
-      dest = pipe_surface_map(surface);
+      dest = screen->surface_map(screen, surface,
+                                 PIPE_BUFFER_USAGE_CPU_WRITE);
 
       /* Put image into texture surface.
        * Note that the image is actually going to be upside down in
@@ -376,7 +383,7 @@ make_texture(struct st_context *st,
                                     mformat,          /* gl_texture_format */
                                     dest,             /* dest */
                                     0, 0, 0,          /* dstX/Y/Zoffset */
-                                    surface->pitch * cpp, /* dstRowStride, bytes */
+                                    surface->stride,  /* dstRowStride, bytes */
                                     &dstImageOffsets, /* dstImageOffsets */
                                     width, height, 1, /* size */
                                     format, type,     /* src format/type */
@@ -384,9 +391,8 @@ make_texture(struct st_context *st,
                                     unpack);
 
       /* unmap */
-      pipe_surface_unmap(surface);
+      screen->surface_unmap(screen, surface);
       pipe_surface_reference(&surface, NULL);
-      pipe->texture_update(pipe, pt, 0, 0x1);
 
       assert(success);
 
@@ -394,111 +400,106 @@ make_texture(struct st_context *st,
       ctx->_ImageTransferState = imageTransferStateSave;
    }
 
-   _mesa_unmap_drapix_pbo(ctx, unpack);
+   _mesa_unmap_drawpix_pbo(ctx, unpack);
 
    return pt;
 }
 
 
 /**
- * Draw textured quad.
+ * Draw quad with texcoords and optional color.
  * Coords are window coords with y=0=bottom.
+ * \param color  may be null
+ * \param invertTex  if true, flip texcoords vertically
  */
 static void
 draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
-          GLfloat x1, GLfloat y1, GLboolean invertTex)
+          GLfloat x1, GLfloat y1, const GLfloat *color,
+          GLboolean invertTex)
 {
-   GLfloat verts[4][2][4]; /* four verts, two attribs, XYZW */
-   GLuint i;
-   GLfloat sLeft = 0.0, sRight = 1.0;
-   GLfloat tTop = invertTex, tBot = 1.0 - tTop;
-
-   /* upper-left */
-   verts[0][0][0] = x0;    /* attr[0].x */
-   verts[0][0][1] = y0;    /* attr[0].y */
-   verts[0][1][0] = sLeft; /* attr[1].s */
-   verts[0][1][1] = tTop;  /* attr[1].t */
-
-   /* upper-right */
-   verts[1][0][0] = x1;
-   verts[1][0][1] = y0;
-   verts[1][1][0] = sRight;
-   verts[1][1][1] = tTop;
-
-   /* lower-right */
-   verts[2][0][0] = x1;
-   verts[2][0][1] = y1;
-   verts[2][1][0] = sRight;
-   verts[2][1][1] = tBot;
-
-   /* lower-left */
-   verts[3][0][0] = x0;
-   verts[3][0][1] = y1;
-   verts[3][1][0] = sLeft;
-   verts[3][1][1] = tBot;
-
-   /* same for all verts: */
-   for (i = 0; i < 4; i++) {
-      verts[i][0][2] = z;   /*Z*/
-      verts[i][0][3] = 1.0; /*W*/
-      verts[i][1][2] = 0.0; /*R*/
-      verts[i][1][3] = 1.0; /*Q*/
-   }
-
-   st_draw_vertices(ctx, PIPE_PRIM_QUADS, 4, (float *) verts, 2, GL_FALSE);
-}
-
-
-static void
-draw_quad_colored(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
-                  GLfloat x1, GLfloat y1, const GLfloat *color,
-                  GLboolean invertTex)
-{
-   GLfloat bias = ctx->st->bitmap_texcoord_bias;
+   struct st_context *st = ctx->st;
+   struct pipe_context *pipe = ctx->st->pipe;
    GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */
-   GLuint i;
-   GLfloat xBias = bias / (x1-x0);
-   GLfloat yBias = bias / (y1-y0);
-   GLfloat sLeft = 0.0 + xBias, sRight = 1.0 + xBias;
-   GLfloat tTop = invertTex - yBias, tBot = 1.0 - tTop - yBias;
-
-   /* upper-left */
-   verts[0][0][0] = x0;    /* attr[0].x */
-   verts[0][0][1] = y0;    /* attr[0].y */
-   verts[0][2][0] = sLeft; /* attr[2].s */
-   verts[0][2][1] = tTop;  /* attr[2].t */
-
-   /* upper-right */
-   verts[1][0][0] = x1;
-   verts[1][0][1] = y0;
-   verts[1][2][0] = sRight;
-   verts[1][2][1] = tTop;
-
-   /* lower-right */
-   verts[2][0][0] = x1;
-   verts[2][0][1] = y1;
-   verts[2][2][0] = sRight;
-   verts[2][2][1] = tBot;
-
-   /* lower-left */
-   verts[3][0][0] = x0;
-   verts[3][0][1] = y1;
-   verts[3][2][0] = sLeft;
-   verts[3][2][1] = tBot;
-
-   /* same for all verts: */
-   for (i = 0; i < 4; i++) {
-      verts[i][0][2] = z;   /*Z*/
-      verts[i][0][3] = 1.0; /*W*/
-      verts[i][1][0] = color[0];
-      verts[i][1][1] = color[1];
-      verts[i][1][2] = color[2];
-      verts[i][1][3] = color[3];
-      verts[i][2][2] = 0.0; /*R*/
-      verts[i][2][3] = 1.0; /*Q*/
+
+   /* setup vertex data */
+   {
+      const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+      const GLfloat fb_width = (GLfloat) fb->Width;
+      const GLfloat fb_height = (GLfloat) fb->Height;
+      const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f;
+      const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f;
+      const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f;
+      const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f;
+      const GLfloat sLeft = 0.0f, sRight = 1.0f;
+      const GLfloat tTop = invertTex, tBot = 1.0f - tTop;
+      GLuint tex, i;
+
+      /* upper-left */
+      verts[0][0][0] = clip_x0;    /* v[0].attr[0].x */
+      verts[0][0][1] = clip_y0;    /* v[0].attr[0].y */
+
+      /* upper-right */
+      verts[1][0][0] = clip_x1;
+      verts[1][0][1] = clip_y0;
+
+      /* lower-right */
+      verts[2][0][0] = clip_x1;
+      verts[2][0][1] = clip_y1;
+
+      /* lower-left */
+      verts[3][0][0] = clip_x0;
+      verts[3][0][1] = clip_y1;
+
+      tex = color ? 2 : 1;
+      verts[0][tex][0] = sLeft; /* v[0].attr[tex].s */
+      verts[0][tex][1] = tTop;  /* v[0].attr[tex].t */
+      verts[1][tex][0] = sRight;
+      verts[1][tex][1] = tTop;
+      verts[2][tex][0] = sRight;
+      verts[2][tex][1] = tBot;
+      verts[3][tex][0] = sLeft;
+      verts[3][tex][1] = tBot;
+
+      /* same for all verts: */
+      if (color) {
+         for (i = 0; i < 4; i++) {
+            verts[i][0][2] = z;   /*Z*/
+            verts[i][0][3] = 1.0f; /*W*/
+            verts[i][1][0] = color[0];
+            verts[i][1][1] = color[1];
+            verts[i][1][2] = color[2];
+            verts[i][1][3] = color[3];
+            verts[i][2][2] = 0.0f; /*R*/
+            verts[i][2][3] = 1.0f; /*Q*/
+         }
+      }
+      else {
+         for (i = 0; i < 4; i++) {
+            verts[i][0][2] = z;   /*Z*/
+            verts[i][0][3] = 1.0f; /*W*/
+            verts[i][1][2] = 0.0f; /*R*/
+            verts[i][1][3] = 1.0f; /*Q*/
+         }
+      }
    }
 
-   st_draw_vertices(ctx, PIPE_PRIM_QUADS, 4, (float *) verts, 3, GL_FALSE);
+   {
+      struct pipe_buffer *buf;
+      ubyte *map;
+
+      /* allocate/load buffer object with vertex data */
+      buf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
+                               sizeof(verts));
+      map = pipe_buffer_map(pipe->screen, buf, PIPE_BUFFER_USAGE_CPU_WRITE);
+      memcpy(map, verts, sizeof(verts));
+      pipe_buffer_unmap(pipe->screen, buf);
+
+      util_draw_vertex_buffer(pipe, buf,
+                              PIPE_PRIM_QUADS,
+                              4,  /* verts */
+                              3); /* attribs/vert */
+      pipe_buffer_reference(pipe->screen, &buf, NULL);
+   }
 }
 
 
@@ -517,7 +518,7 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
    struct pipe_context *pipe = ctx->st->pipe;
    struct cso_context *cso = ctx->st->cso_context;
    GLfloat x0, y0, x1, y1;
-   GLuint maxSize;
+   GLsizei maxSize;
 
    /* limit checks */
    /* XXX if DrawPixels image is larger than max texture size, break
@@ -530,22 +531,24 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
    cso_save_rasterizer(cso);
    cso_save_viewport(cso);
    cso_save_samplers(cso);
+   cso_save_sampler_textures(cso);
+   cso_save_fragment_shader(cso);
+   cso_save_vertex_shader(cso);
 
    /* rasterizer state: just scissor */
    {
       struct pipe_rasterizer_state rasterizer;
       memset(&rasterizer, 0, sizeof(rasterizer));
-      if (ctx->Scissor.Enabled)
-         rasterizer.scissor = 1;
-
+      rasterizer.gl_rasterization_rules = 1;
+      rasterizer.scissor = ctx->Scissor.Enabled;
       cso_set_rasterizer(cso, &rasterizer);
    }
 
    /* fragment shader state: TEX lookup program */
-   pipe->bind_fs_state(pipe, stfp->driver_shader);
+   cso_set_fragment_shader_handle(cso, stfp->driver_shader);
 
    /* vertex shader state: position + texcoord pass-through */
-   pipe->bind_vs_state(pipe, stvp->driver_shader);
+   cso_set_vertex_shader_handle(cso, stvp->driver_shader);
 
 
    /* texture sampling state: */
@@ -561,27 +564,36 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
       sampler.normalized_coords = 1;
 
       cso_single_sampler(cso, 0, &sampler);
+      if (st->pixel_xfer.pixelmap_enabled) {
+         cso_single_sampler(cso, 1, &sampler);
+      }
       cso_single_sampler_done(cso);
    }
 
    /* viewport state: viewport matching window dims */
    {
-      const float width = ctx->DrawBuffer->Width;
-      const float height = ctx->DrawBuffer->Height;
+      const float width = (float) ctx->DrawBuffer->Width;
+      const float height = (float) ctx->DrawBuffer->Height;
       struct pipe_viewport_state vp;
-      vp.scale[0] =  0.5 * width;
-      vp.scale[1] = -0.5 * height;
-      vp.scale[2] = 1.0;
-      vp.scale[3] = 1.0;
-      vp.translate[0] = 0.5 * width;
-      vp.translate[1] = 0.5 * height;
-      vp.translate[2] = 0.0;
-      vp.translate[3] = 0.0;
+      vp.scale[0] =  0.5f * width;
+      vp.scale[1] = -0.5f * height;
+      vp.scale[2] = 1.0f;
+      vp.scale[3] = 1.0f;
+      vp.translate[0] = 0.5f * width;
+      vp.translate[1] = 0.5f * height;
+      vp.translate[2] = 0.0f;
+      vp.translate[3] = 0.0f;
       cso_set_viewport(cso, &vp);
    }
 
    /* texture state: */
-   {
+   if (st->pixel_xfer.pixelmap_enabled) {
+      struct pipe_texture *textures[2];
+      textures[0] = pt;
+      textures[1] = st->pixel_xfer.pixelmap_texture;
+      pipe->set_sampler_textures(pipe, 2, textures);
+   }
+   else {
       pipe->set_sampler_textures(pipe, 1, &pt);
    }
 
@@ -589,27 +601,21 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
     * Recall that these coords are transformed by the current
     * vertex shader and viewport transformation.
     */
-   x0 = x;
+   x0 = (GLfloat) x;
    x1 = x + width * ctx->Pixel.ZoomX;
-   y0 = y;
+   y0 = (GLfloat) y;
    y1 = y + height * ctx->Pixel.ZoomY;
-
-   /* draw textured quad */
-   if (color)
-      draw_quad_colored(ctx, x0, y0, z, x1, y1, color, invertTex);
-   else
-      draw_quad(ctx, x0, y0, z, x1, y1, invertTex);
-
+   //if(!color)
+   draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex);
+   //else
+   //printf("skip draw quad\n");
    /* restore state */
    cso_restore_rasterizer(cso);
    cso_restore_viewport(cso);
    cso_restore_samplers(cso);
-   /* shaders don't go through cso yet */
-   pipe->bind_fs_state(pipe, st->fp->driver_shader);
-   pipe->bind_vs_state(pipe, st->vp->driver_shader);
-
-   pipe->set_sampler_textures(pipe, ctx->st->state.num_textures,
-                              ctx->st->state.sampler_texture);
+   cso_restore_sampler_textures(cso);
+   cso_restore_fragment_shader(cso);
+   cso_restore_vertex_shader(cso);
 }
 
 
@@ -732,15 +738,23 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
 {
    struct st_context *st = ctx->st;
    struct pipe_context *pipe = st->pipe;
-   struct pipe_surface *ps = st->state.framebuffer.zsbuf;
+   struct pipe_screen *screen = pipe->screen;
+   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 = pipe_surface_map(ps);
+   stmap = screen->surface_map(screen, ps, 
+                               PIPE_BUFFER_USAGE_CPU_WRITE);
 
    /* if width > MAX_WIDTH, have to process image in chunks */
    skipPixels = 0;
@@ -771,15 +785,15 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
             }
 
             switch (ps->format) {
-            case PIPE_FORMAT_U_S8:
+            case PIPE_FORMAT_S8_UNORM:
                {
-                  ubyte *dest = stmap + spanY * ps->pitch + spanX;
+                  ubyte *dest = stmap + spanY * ps->stride + spanX;
                   memcpy(dest, values, spanWidth);
                }
                break;
             case PIPE_FORMAT_S8Z24_UNORM:
                {
-                  uint *dest = (uint *) stmap + spanY * ps->pitch + spanX;
+                  uint *dest = (uint *) (stmap + spanY * ps->stride + spanX*4);
                   GLint k;
                   for (k = 0; k < spanWidth; k++) {
                      uint p = dest[k];
@@ -797,7 +811,8 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
    }
 
    /* unmap the stencil buffer */
-   pipe_surface_unmap(ps);
+   screen->surface_unmap(screen, ps);
+   pipe_surface_reference(&ps, NULL);
 }
 
 
@@ -821,6 +836,9 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
       return;
    }
 
+   _mesa_set_vp_override( ctx, TRUE );
+   _mesa_update_state( ctx );
+
    st_validate_state(st);
 
    if (format == GL_DEPTH_COMPONENT) {
@@ -860,6 +878,8 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
       /* blit */
       draw_blit(st, width, height, format, type, pixels);
    }
+
+   _mesa_set_vp_override( ctx, FALSE );
 }
 
 
@@ -869,11 +889,10 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
                     GLsizei width, GLsizei height,
                     GLint dstx, GLint dsty)
 {
-   struct st_renderbuffer *rbRead = st_renderbuffer(ctx->ReadBuffer->_StencilBuffer);
    struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer);
-   struct pipe_surface *psRead = rbRead->surface;
-   struct pipe_surface *psDraw = rbDraw->surface;
-   ubyte *readMap, *drawMap;
+   struct pipe_screen *screen = ctx->st->pipe->screen;
+   struct pipe_surface *psDraw;
+   ubyte *drawMap;
    ubyte *buffer;
    int i;
 
@@ -883,14 +902,19 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
       return;
    }
 
-   /* map the stencil buffers */
-   readMap = pipe_surface_map(psRead);
-   drawMap = pipe_surface_map(psDraw);
-
    /* this will do stencil pixel transfer ops */
    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);
+
+   assert(psDraw->block.width == 1);
+   assert(psDraw->block.height == 1);
+   
+   /* map the stencil buffer */
+   drawMap = screen->surface_map(screen, psDraw, PIPE_BUFFER_USAGE_CPU_WRITE);
+
    /* draw */
    /* XXX PixelZoom not handled yet */
    for (i = 0; i < height; i++) {
@@ -904,7 +928,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
          y = ctx->DrawBuffer->Height - y - 1;
       }
 
-      dst = drawMap + (y * psDraw->pitch + dstx) * psDraw->cpp;
+      dst = drawMap + y * psDraw->stride + dstx * psDraw->block.size;
       src = buffer + i * width;
 
       switch (psDraw->format) {
@@ -918,7 +942,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
             }
          }
          break;
-      case PIPE_FORMAT_U_S8:
+      case PIPE_FORMAT_S8_UNORM:
          memcpy(dst, src, width);
          break;
       default:
@@ -928,9 +952,9 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
 
    free(buffer);
 
-   /* unmap the stencil buffers */
-   pipe_surface_unmap(psRead);
-   pipe_surface_unmap(psDraw);
+   /* unmap the stencil buffer */
+   screen->surface_unmap(screen, psDraw);
+   pipe_surface_reference(&psDraw, NULL);
 }
 
 
@@ -945,7 +969,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;
@@ -963,7 +986,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
    }
 
    if (type == GL_COLOR) {
-      rbRead = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
+      rbRead = st_get_color_read_renderbuffer(ctx);
       color = NULL;
       stfp = combined_drawpix_fragment_program(ctx);
       stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE);
@@ -976,85 +999,87 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
       stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
    }
 
-   psRead = rbRead->surface;
-   srcFormat = psRead->format;
+   srcFormat = rbRead->texture->format;
 
-   if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE)) {
+   if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D, 
+                                   PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
       texFormat = srcFormat;
    }
    else {
       /* srcFormat can't be used as a texture format */
       if (type == GL_DEPTH) {
-         static const enum pipe_format zFormats[] = {
-            PIPE_FORMAT_Z16_UNORM,
-            PIPE_FORMAT_Z32_UNORM,
-            PIPE_FORMAT_S8Z24_UNORM,
-            PIPE_FORMAT_Z24S8_UNORM
-         };
-         uint i;
-         texFormat = 0;
-         for (i = 0; i < Elements(zFormats); i++) {
-            if (screen->is_format_supported(screen, zFormats[i],
-                                            PIPE_TEXTURE)) {
-               texFormat = zFormats[i];
-               break;
-            }
-         }
-         assert(texFormat); /* XXX no depth texture formats??? */
+         texFormat = st_choose_format(pipe, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D, 
+                                      PIPE_TEXTURE_USAGE_DEPTH_STENCIL);
+         assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */
       }
       else {
-         /* todo */
-         assert(0);
+         /* default color format */
+         texFormat = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D, 
+                                      PIPE_TEXTURE_USAGE_SAMPLER);
+         assert(texFormat != PIPE_FORMAT_NONE);
       }
    }
 
    pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0,
-                          width, height, 1, 0);
+                          width, height, 1, 0,
+                          PIPE_TEXTURE_USAGE_SAMPLER);
    if (!pt)
       return;
 
-   psTex = screen->get_tex_surface(screen, pt, 0, 0, 0);
-
    if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
       srcy = ctx->DrawBuffer->Height - srcy - height;
    }
 
-   /* For some drivers (like Xlib) it's not possible to treat the
-    * front/back color buffers as surfaces (they're XImages and Pixmaps).
-    * So, this var tells us if we can use surface_copy here...
-    */
-   if (st->haveFramebufferSurfaces && 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, 
+                                      PIPE_BUFFER_USAGE_GPU_WRITE );
       pipe->surface_copy(pipe,
                          FALSE,
                         psTex, /* dest */
                         0, 0, /* destx/y */
                         psRead,
                         srcx, srcy, width, height);
+      pipe_surface_reference(&psRead, NULL);
    }
-   else if (type == GL_COLOR) {
-      /* alternate path using get/put_tile() */
-      GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
+   else {
+      /* CPU-based fallback/conversion */
+      struct pipe_surface *psRead = screen->get_tex_surface(screen,
+                                       rbRead->texture, 0, 0, 0,
+                                       PIPE_BUFFER_USAGE_CPU_READ);
 
-      pipe_get_tile_rgba(pipe, psRead, srcx, srcy, width, height, buf);
-      pipe_put_tile_rgba(pipe, psTex, 0, 0, width, height, buf);
+      psTex = screen->get_tex_surface(screen, pt, 0, 0, 0, 
+                                      PIPE_BUFFER_USAGE_CPU_WRITE );
 
-      free(buf);
-   }
-   else {
-      /* GL_DEPTH */
-      GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint));
-      pipe_get_tile_z(pipe, psRead, srcx, srcy, width, height, buf);
-      pipe_put_tile_z(pipe, psTex, 0, 0, width, height, buf);
-      free(buf);
+      if (type == GL_COLOR) {
+         /* alternate path using get/put_tile() */
+         GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
+
+         pipe_get_tile_rgba(psRead, srcx, srcy, width, height, buf);
+         pipe_put_tile_rgba(psTex, 0, 0, width, height, buf);
+
+         free(buf);
+      }
+      else {
+         /* GL_DEPTH */
+         GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint));
+         pipe_get_tile_z(psRead, srcx, srcy, width, height, buf);
+         pipe_put_tile_z(psTex, 0, 0, width, height, buf);
+         free(buf);
+      }
+      pipe_surface_reference(&psRead, NULL);
    }
 
+   pipe_surface_reference(&psTex, NULL);
+
    /* draw textured quad */
    draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
                       width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
                       pt, stvp, stfp, color, GL_TRUE);
 
-   pipe_surface_reference(&psTex, NULL);
    pipe_texture_reference(&pt, NULL);
 }
 
@@ -1065,3 +1090,15 @@ void st_init_drawpixels_functions(struct dd_function_table *functions)
    functions->DrawPixels = st_DrawPixels;
    functions->CopyPixels = st_CopyPixels;
 }
+
+
+void
+st_destroy_drawpix(struct st_context *st)
+{
+   st_reference_fragprog(st, &st->drawpix.z_shader, NULL);
+   st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
+   st_reference_vertprog(st, &st->drawpix.vert_shaders[0], NULL);
+   st_reference_vertprog(st, &st->drawpix.vert_shaders[1], NULL);
+}
+
+