checkpoint: code refactoring for glCopyPixels
authorBrian <brian.paul@tungstengraphics.com>
Thu, 18 Oct 2007 19:27:10 +0000 (13:27 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Thu, 18 Oct 2007 19:27:10 +0000 (13:27 -0600)
src/mesa/state_tracker/st_cb_drawpixels.c

index 03fc134..858ce17 100644 (file)
 /**
  * Create a simple fragment shader that does a TEX() instruction to get
  * the fragment color.
+ * If bitmapMode, use KIL instruction to kill the "0-pixels".
  */
 static struct st_fragment_program *
 make_fragment_shader(struct st_context *st, GLboolean bitmapMode)
 {
+   /* only make programs once and re-use */
+   static struct st_fragment_program *progs[2] = { NULL, NULL };
    GLcontext *ctx = st->ctx;
    struct st_fragment_program *stfp;
    struct gl_program *p;
    GLuint ic = 0;
 
+   if (progs[bitmapMode])
+      return progs[bitmapMode];
+
    p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
    if (!p)
       return NULL;
@@ -159,6 +165,8 @@ make_fragment_shader(struct st_context *st, GLboolean bitmapMode)
    st_translate_fragment_program(st, stfp, NULL,
                                  stfp->tokens, ST_MAX_SHADER_TOKENS);
 
+   progs[bitmapMode] = stfp;
+
    return stfp;
 }
 
@@ -166,15 +174,20 @@ make_fragment_shader(struct st_context *st, GLboolean bitmapMode)
 /**
  * Create fragment shader that does a TEX() instruction to get a Z
  * value, then writes to FRAG_RESULT_DEPR.
+ * Pass fragment color through as-is.
  */
 static struct st_fragment_program *
 make_fragment_shader_z(struct st_context *st)
 {
    GLcontext *ctx = st->ctx;
-   struct st_fragment_program *stfp;
+   /* 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;
+
    p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
    if (!p)
       return NULL;
@@ -226,16 +239,21 @@ make_fragment_shader_z(struct st_context *st)
 
 /**
  * Create a simple vertex shader that just passes through the
- * vertex position and texcoord (and color).
+ * vertex position and texcoord (and optionally, color).
  */
 static struct st_vertex_program *
 make_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];
+
    p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
    if (!p)
       return NULL;
@@ -292,6 +310,8 @@ make_vertex_shader(struct st_context *st, GLboolean passColor)
    st_translate_vertex_program(st, stvp, NULL,
                                stvp->tokens, ST_MAX_SHADER_TOKENS);
 
+   progs[passColor] = stvp;
+
    return stvp;
 }
 
@@ -311,8 +331,51 @@ _mesa_base_format(GLenum format)
 
 
 
+static struct pipe_mipmap_tree *
+alloc_mipmap_tree(struct st_context *st,
+                  GLsizei width, GLsizei height, uint pipeFormat)
+{
+   const GLbitfield flags = PIPE_SURFACE_FLAG_TEXTURE;
+   struct pipe_mipmap_tree *mt;
+   GLuint cpp;
+
+   mt = CALLOC_STRUCT(pipe_mipmap_tree);
+   if (!mt)
+      return NULL;
+
+   cpp = st_sizeof_format(pipeFormat);
+
+   /* allocate texture region/storage */
+   mt->region = st->pipe->region_alloc(st->pipe, cpp, width, height, flags);
+
+   mt->target = PIPE_TEXTURE_2D;
+   mt->internal_format = GL_RGBA;
+   mt->format = pipeFormat;
+   mt->first_level = 0;
+   mt->last_level = 0;
+   mt->width0 = width;
+   mt->height0 = height;
+   mt->depth0 = 1;
+   mt->cpp = cpp;
+   mt->compressed = 0;
+   mt->pitch = mt->region->pitch;
+   mt->depth_pitch = 0;
+   mt->total_height = height;
+   mt->level[0].level_offset = 0;
+   mt->level[0].width = width;
+   mt->level[0].height = height;
+   mt->level[0].depth = 1;
+   mt->level[0].nr_images = 1;
+   mt->level[0].image_offset = NULL;
+   mt->refcount = 1;
+
+   return mt;
+}
+
+
 /**
- * Make mipmap tree containing the glDrawPixels image.
+ * Make mipmap tree containing an image for glDrawPixels image.
+ * If 'pixels' is NULL, leave the texture image data undefined.
  */
 static struct pipe_mipmap_tree *
 make_mipmap_tree(struct st_context *st,
@@ -322,7 +385,6 @@ make_mipmap_tree(struct st_context *st,
 {
    struct pipe_context *pipe = st->pipe;
    const struct gl_texture_format *mformat;
-   const GLbitfield flags = PIPE_SURFACE_FLAG_TEXTURE;
    struct pipe_mipmap_tree *mt;
    GLuint pipeFormat, cpp;
    GLenum baseFormat;
@@ -336,7 +398,7 @@ make_mipmap_tree(struct st_context *st,
    assert(pipeFormat);
    cpp = st_sizeof_format(pipeFormat);
 
-   mt = CALLOC_STRUCT(pipe_mipmap_tree);
+   mt = alloc_mipmap_tree(st, width, height, pipeFormat);
    if (!mt)
       return NULL;
 
@@ -346,15 +408,12 @@ make_mipmap_tree(struct st_context *st,
       */
       printf("st_DrawPixels (sourcing from PBO not implemented yet)\n");
    }
-   else {
+
+   {
       static const GLuint dstImageOffsets = 0;
       GLboolean success;
+      GLuint pitch = mt->region->pitch;
       GLubyte *dest;
-      GLuint pitch;
-
-      /* allocate texture region/storage */
-      mt->region = st->pipe->region_alloc(st->pipe, cpp, width, height, flags);
-      pitch = mt->region->pitch;
 
       /* map texture region */
       dest = pipe->region_map(pipe, mt->region);
@@ -377,10 +436,10 @@ make_mipmap_tree(struct st_context *st,
 
       /* unmap */
       pipe->region_unmap(pipe, mt->region);
-
       assert(success);
    }
 
+#if 0
    mt->target = PIPE_TEXTURE_2D;
    mt->internal_format = GL_RGBA;
    mt->format = pipeFormat;
@@ -401,7 +460,7 @@ make_mipmap_tree(struct st_context *st,
    mt->level[0].nr_images = 1;
    mt->level[0].image_offset = NULL;
    mt->refcount = 1;
-
+#endif
    return mt;
 }
 
@@ -804,10 +863,6 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
               GLenum format, GLenum type,
               const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
 {
-   static struct st_fragment_program *stfp_c = NULL; /* color */
-   static struct st_fragment_program *stfp_z = NULL; /* z */
-   static struct st_vertex_program *stvp_t = NULL;  /* just emit texcoord */
-   static struct st_vertex_program *stvp_c = NULL;  /* emit color too */
    struct st_fragment_program *stfp;
    struct st_vertex_program *stvp;
    struct st_context *st = ctx->st;
@@ -820,28 +875,12 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
       return;
    }
 
-   /* create the fragment programs if needed */
-   if (!stfp_c) {
-      stfp_c = make_fragment_shader(ctx->st, GL_FALSE);
-   }
-   if (!stfp_z) {
-      stfp_z = make_fragment_shader_z(ctx->st);
-   }
-
-   /* and vertex programs */
-   if (!stvp_t) {
-      stvp_t = make_vertex_shader(ctx->st, GL_FALSE);
-   }
-   if (!stvp_c) {
-      stvp_c = make_vertex_shader(ctx->st, GL_TRUE);
-   }
-
    st_validate_state(st);
 
    if (format == GL_DEPTH_COMPONENT) {
       ps = st->state.framebuffer.zbuf;
-      stfp = stfp_z;
-      stvp = stvp_c;
+      stfp = make_fragment_shader_z(ctx->st);
+      stvp = make_vertex_shader(ctx->st, GL_TRUE);
       color = ctx->Current.RasterColor;
    }
    else if (format == GL_STENCIL_INDEX) {
@@ -851,8 +890,8 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
    }
    else {
       ps = st->state.framebuffer.cbufs[0];
-      stfp = stfp_c;
-      stvp = stvp_t;
+      stfp = make_fragment_shader(ctx->st, GL_FALSE);
+      stvp = make_vertex_shader(ctx->st, GL_FALSE);
       color = NULL;
    }
 
@@ -1032,19 +1071,16 @@ static void
 st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
           const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
 {
-   static struct st_vertex_program *stvp = NULL;
-   static struct st_fragment_program *stfp = NULL;
+   struct st_vertex_program *stvp;
+   struct st_fragment_program *stfp;
    struct st_context *st = ctx->st;
    struct pipe_mipmap_tree *mt;
 
-   /* create the fragment program if needed */
-   if (!stfp) {
-      stfp = make_fragment_shader(ctx->st, GL_TRUE);
-   }
+   /* create the fragment program */
+   stfp = make_fragment_shader(ctx->st, GL_TRUE);
+
    /* and vertex program */
-   if (!stvp) {
-      stvp = make_vertex_shader(ctx->st, GL_TRUE);
-   }
+   stvp = make_vertex_shader(ctx->st, GL_TRUE);
 
    st_validate_state(st);
 
@@ -1138,22 +1174,59 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
               GLint dstx, GLint dsty, GLenum type)
 {
    struct st_context *st = ctx->st;
+   struct pipe_context *pipe = st->pipe;
+   struct st_renderbuffer *rbRead;
+   struct st_vertex_program *stvp;
+   struct st_fragment_program *stfp;
+   struct pipe_surface *psRead;
+   struct pipe_mipmap_tree *mt;
+   GLfloat *color;
+   uint format;
 
    st_validate_state(st);
 
    if (type == GL_STENCIL) {
+      /* can't use texturing to do stencil */
       copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
       return;
    }
 
-   /* allocate a texture of size width x height */
+   if (type == GL_COLOR) {
+      rbRead = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
+      color = NULL;
+      stfp = make_fragment_shader(ctx->st, GL_FALSE);
+      stvp = make_vertex_shader(ctx->st, GL_FALSE);
+   }
+   else {
+      rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
+      color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+      stfp = make_fragment_shader_z(ctx->st);
+      stvp = make_vertex_shader(ctx->st, GL_TRUE);
+   }
+
+   psRead = rbRead->surface;
+   format = psRead->format;
 
-   /* blit/copy framebuffer region into texture */
+   mt = alloc_mipmap_tree(ctx->st, width, height, format);
+   if (!mt)
+      return;
 
-   /* draw textured quad */
+   /* copy source framebuffer region into mipmap/texture */
+   pipe->region_copy(pipe,
+                     mt->region, /* dest */
+                     0, /* dest_offset */
+                     0, 0, /* destx/y */
+                     psRead->region,
+                     0, /* src_offset */
+                     srcx, srcy, width, height);
 
 
-   fprintf(stderr, "st_CopyPixels not implemented yet\n");
+   /* draw textured quad */
+   draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
+                      width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
+                      mt, stvp, stfp, color);
+
+   free_mipmap_tree(st->pipe, mt);
 }