gallium: new pixel blit code
authorBrian <brian.paul@tungstengraphics.com>
Tue, 18 Mar 2008 23:04:59 +0000 (17:04 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Tue, 18 Mar 2008 23:18:11 +0000 (17:18 -0600)
Copy rectangular region from one surface to another w/ scaling.
Disables most fragment operations.

src/gallium/auxiliary/util/Makefile
src/gallium/auxiliary/util/SConscript
src/gallium/auxiliary/util/u_blit.c [new file with mode: 0644]
src/gallium/auxiliary/util/u_blit.h [new file with mode: 0644]

index 7af9b35d4b6c64c2303c9bcf8c745b9cad51fe58..9b6c2708b62cb5a64b262255df3156d863876a1f 100644 (file)
@@ -7,6 +7,7 @@ C_SOURCES = \
        p_debug.c \
        p_tile.c \
        p_util.c \
+       u_blit.c \
        u_draw_quad.c \
        u_gen_mipmap.c \
        u_handle_table.c \
index 0eb1b8d9da3475f631760e743b9cda93f3d1c992..b44f2d5e3987d6f867e7978ec17e795791d2e774 100644 (file)
@@ -6,6 +6,7 @@ util = env.ConvenienceLibrary(
                'p_debug.c',
                'p_tile.c',
                'p_util.c',
+               'u_blit.c',
                'u_draw_quad.c',
                'u_gen_mipmap.c',
                'u_handle_table.c',
diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
new file mode 100644 (file)
index 0000000..4b4ab81
--- /dev/null
@@ -0,0 +1,276 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Copy/blit pixel rect between surfaces
+ *  
+ * @author Brian Paul
+ */
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_debug.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "util/u_draw_quad.h"
+#include "util/u_blit.h"
+#include "util/u_simple_shaders.h"
+
+
+struct blit_state
+{
+   struct pipe_context *pipe;
+
+   void *blend;
+   void *depthstencil;
+   void *rasterizer;
+   void *samplers[2];  /* one for linear, one for nearest sampling */
+
+   /*struct pipe_viewport_state viewport;*/
+   struct pipe_sampler_state *vs;
+   struct pipe_sampler_state *fs;
+};
+
+
+/**
+ * Create state object for blit.
+ * Intended to be created once and re-used for many blit() calls.
+ */
+struct blit_state *
+util_create_blit(struct pipe_context *pipe)
+{
+   struct pipe_blend_state blend;
+   struct pipe_depth_stencil_alpha_state depthstencil;
+   struct pipe_rasterizer_state rasterizer;
+   struct blit_state *ctx;
+   struct pipe_sampler_state sampler;
+
+   ctx = CALLOC_STRUCT(blit_state);
+   if (!ctx)
+      return NULL;
+
+   ctx->pipe = pipe;
+
+   /* we don't use blending, but need to set valid values */
+   memset(&blend, 0, sizeof(blend));
+   blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+   blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+   blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+   blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+   blend.colormask = PIPE_MASK_RGBA;
+   ctx->blend = pipe->create_blend_state(pipe, &blend);
+
+   /* depth/stencil/alpha */
+   memset(&depthstencil, 0, sizeof(depthstencil));
+   ctx->depthstencil = pipe->create_depth_stencil_alpha_state(pipe, &depthstencil);
+
+   /* rasterizer */
+   memset(&rasterizer, 0, sizeof(rasterizer));
+   rasterizer.front_winding = PIPE_WINDING_CW;
+   rasterizer.cull_mode = PIPE_WINDING_NONE;
+   rasterizer.bypass_clipping = 1;  /* bypasses viewport too */
+   /*rasterizer.bypass_vs = 1;*/
+   ctx->rasterizer = pipe->create_rasterizer_state(pipe, &rasterizer);
+
+   /* samplers */
+   memset(&sampler, 0, sizeof(sampler));
+   sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+   sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+   sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+   sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+   sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+   sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+   sampler.normalized_coords = 1;
+   ctx->samplers[0] = pipe->create_sampler_state(pipe, &sampler);
+
+   sampler.min_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
+   sampler.mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
+   ctx->samplers[1] = pipe->create_sampler_state(pipe, &sampler);
+
+
+#if 0
+   /* viewport */
+   ctx->viewport.scale[0] = 1.0;
+   ctx->viewport.scale[1] = 1.0;
+   ctx->viewport.scale[2] = 1.0;
+   ctx->viewport.scale[3] = 1.0;
+   ctx->viewport.translate[0] = 0.0;
+   ctx->viewport.translate[1] = 0.0;
+   ctx->viewport.translate[2] = 0.0;
+   ctx->viewport.translate[3] = 0.0;
+#endif
+
+   /* vertex shader */
+   {
+      const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+                                      TGSI_SEMANTIC_GENERIC };
+      const uint semantic_indexes[] = { 0, 0 };
+      ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
+                                                    semantic_indexes);
+   }
+
+   /* fragment shader */
+   ctx->fs = util_make_fragment_tex_shader(pipe);
+
+   return ctx;
+}
+
+
+/**
+ * Destroy a blit context
+ */
+void
+util_destroy_blit(struct blit_state *ctx)
+{
+   struct pipe_context *pipe = ctx->pipe;
+
+   pipe->delete_blend_state(pipe, ctx->blend);
+   pipe->delete_depth_stencil_alpha_state(pipe, ctx->depthstencil);
+   pipe->delete_rasterizer_state(pipe, ctx->rasterizer);
+   pipe->delete_sampler_state(pipe, ctx->samplers[0]);
+   pipe->delete_sampler_state(pipe, ctx->samplers[1]);
+
+   pipe->delete_vs_state(pipe, ctx->vs);
+   pipe->delete_fs_state(pipe, ctx->fs);
+
+   FREE(ctx);
+}
+
+
+/**
+ * Copy pixel block from src surface to dst surface.
+ * Overlapping regions are acceptable.
+ * XXX need some control over blitting Z and/or stencil.
+ */
+void
+util_blit_pixels(struct blit_state *ctx,
+                 struct pipe_surface *src,
+                 int srcX0, int srcY0,
+                 int srcX1, int srcY1,
+                 struct pipe_surface *dst,
+                 int dstX0, int dstY0,
+                 int dstX1, int dstY1,
+                 float z, uint filter)
+{
+   struct pipe_context *pipe = ctx->pipe;
+   struct pipe_screen *screen = pipe->screen;
+   struct pipe_texture texTemp, *tex;
+   struct pipe_surface *texSurf;
+   struct pipe_framebuffer_state fb;
+   const int srcW = abs(srcX1 - srcX0);
+   const int srcH = abs(srcY1 - srcY0);
+   const int srcLeft = MIN2(srcX0, srcX1);
+   const int srcTop = MIN2(srcY0, srcY1);
+
+   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
+          filter == PIPE_TEX_MIPFILTER_LINEAR);
+
+   if (srcLeft != srcX0) {
+      /* left-right flip */
+      int tmp = dstX0;
+      dstX0 = dstX1;
+      dstX1 = tmp;
+   }
+
+   if (srcTop != srcY0) {
+      /* up-down flip */
+      int tmp = dstY0;
+      dstY0 = dstY1;
+      dstY1 = tmp;
+   }
+
+   /*
+    * XXX for now we're always creating a temporary texture.
+    * Strictly speaking that's not always needed.
+    */
+
+   /* create temp texture */
+   memset(&texTemp, 0, sizeof(texTemp));
+   texTemp.target = PIPE_TEXTURE_2D;
+   texTemp.format = src->format;
+   texTemp.last_level = 0;
+   texTemp.width[0] = srcW;
+   texTemp.height[0] = srcH;
+   texTemp.depth[0] = 1;
+   texTemp.compressed = 0;
+   texTemp.cpp = pf_get_bits(src->format) / 8;
+
+   tex = screen->texture_create(screen, &texTemp);
+   if (!tex)
+      return;
+
+   texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0);
+
+   /* load temp texture */
+   pipe->surface_copy(pipe, FALSE,
+                      texSurf, 0, 0,   /* dest */
+                      src, srcLeft, srcTop, /* src */
+                      srcW, srcH);     /* size */
+
+   /* drawing dest */
+   memset(&fb, 0, sizeof(fb));
+   fb.num_cbufs = 1;
+   fb.cbufs[0] = dst;
+   pipe->set_framebuffer_state(pipe, &fb);
+
+   /* sampler */
+   if (filter == PIPE_TEX_MIPFILTER_NEAREST)
+      pipe->bind_sampler_states(pipe, 1, &ctx->samplers[0]);
+   else
+      pipe->bind_sampler_states(pipe, 1, &ctx->samplers[1]);
+
+   /* texture */
+   pipe->set_sampler_textures(pipe, 1, &tex);
+
+   /* shaders */
+   pipe->bind_fs_state(pipe, ctx->fs);
+   pipe->bind_vs_state(pipe, ctx->vs);
+
+   /* misc state */
+   pipe->bind_blend_state(pipe, ctx->blend);
+   pipe->bind_depth_stencil_alpha_state(pipe, ctx->depthstencil);
+   pipe->bind_rasterizer_state(pipe, ctx->rasterizer);
+
+   /* draw quad */
+   util_draw_texquad(pipe, dstX0, dstY0, dstX1, dstY1, z);
+
+   /* unbind */
+   pipe->set_sampler_textures(pipe, 0, NULL);
+   pipe->bind_sampler_states(pipe, 0, NULL);
+
+   /* free stuff */
+   pipe_surface_reference(&texSurf, NULL);
+   screen->texture_release(screen, &tex);
+
+   /* Note: caller must restore pipe/gallium state at this time */
+}
+
diff --git a/src/gallium/auxiliary/util/u_blit.h b/src/gallium/auxiliary/util/u_blit.h
new file mode 100644 (file)
index 0000000..0a8e05f
--- /dev/null
@@ -0,0 +1,60 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef U_BLIT_H
+#define U_BLIT_H
+
+
+struct pipe_context;
+struct pipe_surface;
+
+
+struct copy_pixels_state;
+
+
+extern struct blit_state *
+util_create_blit(struct pipe_context *pipe);
+
+
+extern void
+util_destroy_blit(struct blit_state *ctx);
+
+
+
+extern void
+util_blit_pixels(struct blit_state *ctx,
+                 struct pipe_surface *src,
+                 int srcX0, int srcY0,
+                 int srcX1, int srcY1,
+                 struct pipe_surface *dst,
+                 int dstX0, int dstY0,
+                 int dstX1, int dstY1,
+                 float z, uint filter);
+
+
+#endif