u_blit.c revision 0abe462128a8a0725e006751e553f89fee2d7fa7
1/************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28/** 29 * @file 30 * Copy/blit pixel rect between surfaces 31 * 32 * @author Brian Paul 33 */ 34 35 36#include "pipe/p_context.h" 37#include "pipe/p_debug.h" 38#include "pipe/p_defines.h" 39#include "pipe/p_inlines.h" 40#include "pipe/p_util.h" 41#include "pipe/p_winsys.h" 42#include "pipe/p_shader_tokens.h" 43 44#include "util/u_draw_quad.h" 45#include "util/u_blit.h" 46#include "util/u_simple_shaders.h" 47 48 49struct blit_state 50{ 51 struct pipe_context *pipe; 52 53 void *blend; 54 void *depthstencil; 55 void *rasterizer; 56 void *samplers[2]; /* one for linear, one for nearest sampling */ 57 58 /*struct pipe_viewport_state viewport;*/ 59 struct pipe_sampler_state *vs; 60 struct pipe_sampler_state *fs; 61}; 62 63 64/** 65 * Create state object for blit. 66 * Intended to be created once and re-used for many blit() calls. 67 */ 68struct blit_state * 69util_create_blit(struct pipe_context *pipe) 70{ 71 struct pipe_blend_state blend; 72 struct pipe_depth_stencil_alpha_state depthstencil; 73 struct pipe_rasterizer_state rasterizer; 74 struct blit_state *ctx; 75 struct pipe_sampler_state sampler; 76 77 ctx = CALLOC_STRUCT(blit_state); 78 if (!ctx) 79 return NULL; 80 81 ctx->pipe = pipe; 82 83 /* we don't use blending, but need to set valid values */ 84 memset(&blend, 0, sizeof(blend)); 85 blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; 86 blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; 87 blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 88 blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 89 blend.colormask = PIPE_MASK_RGBA; 90 ctx->blend = pipe->create_blend_state(pipe, &blend); 91 92 /* depth/stencil/alpha */ 93 memset(&depthstencil, 0, sizeof(depthstencil)); 94 ctx->depthstencil = pipe->create_depth_stencil_alpha_state(pipe, &depthstencil); 95 96 /* rasterizer */ 97 memset(&rasterizer, 0, sizeof(rasterizer)); 98 rasterizer.front_winding = PIPE_WINDING_CW; 99 rasterizer.cull_mode = PIPE_WINDING_NONE; 100 rasterizer.bypass_clipping = 1; /* bypasses viewport too */ 101 /*rasterizer.bypass_vs = 1;*/ 102 ctx->rasterizer = pipe->create_rasterizer_state(pipe, &rasterizer); 103 104 /* samplers */ 105 memset(&sampler, 0, sizeof(sampler)); 106 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 107 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 108 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 109 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 110 sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST; 111 sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST; 112 sampler.normalized_coords = 1; 113 ctx->samplers[0] = pipe->create_sampler_state(pipe, &sampler); 114 115 sampler.min_img_filter = PIPE_TEX_MIPFILTER_LINEAR; 116 sampler.mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR; 117 ctx->samplers[1] = pipe->create_sampler_state(pipe, &sampler); 118 119 120#if 0 121 /* viewport */ 122 ctx->viewport.scale[0] = 1.0; 123 ctx->viewport.scale[1] = 1.0; 124 ctx->viewport.scale[2] = 1.0; 125 ctx->viewport.scale[3] = 1.0; 126 ctx->viewport.translate[0] = 0.0; 127 ctx->viewport.translate[1] = 0.0; 128 ctx->viewport.translate[2] = 0.0; 129 ctx->viewport.translate[3] = 0.0; 130#endif 131 132 /* vertex shader */ 133 { 134 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, 135 TGSI_SEMANTIC_GENERIC }; 136 const uint semantic_indexes[] = { 0, 0 }; 137 ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names, 138 semantic_indexes); 139 } 140 141 /* fragment shader */ 142 ctx->fs = util_make_fragment_tex_shader(pipe); 143 144 return ctx; 145} 146 147 148/** 149 * Destroy a blit context 150 */ 151void 152util_destroy_blit(struct blit_state *ctx) 153{ 154 struct pipe_context *pipe = ctx->pipe; 155 156 pipe->delete_blend_state(pipe, ctx->blend); 157 pipe->delete_depth_stencil_alpha_state(pipe, ctx->depthstencil); 158 pipe->delete_rasterizer_state(pipe, ctx->rasterizer); 159 pipe->delete_sampler_state(pipe, ctx->samplers[0]); 160 pipe->delete_sampler_state(pipe, ctx->samplers[1]); 161 162 pipe->delete_vs_state(pipe, ctx->vs); 163 pipe->delete_fs_state(pipe, ctx->fs); 164 165 FREE(ctx); 166} 167 168 169/** 170 * Copy pixel block from src surface to dst surface. 171 * Overlapping regions are acceptable. 172 * XXX need some control over blitting Z and/or stencil. 173 */ 174void 175util_blit_pixels(struct blit_state *ctx, 176 struct pipe_surface *src, 177 int srcX0, int srcY0, 178 int srcX1, int srcY1, 179 struct pipe_surface *dst, 180 int dstX0, int dstY0, 181 int dstX1, int dstY1, 182 float z, uint filter) 183{ 184 struct pipe_context *pipe = ctx->pipe; 185 struct pipe_screen *screen = pipe->screen; 186 struct pipe_texture texTemp, *tex; 187 struct pipe_surface *texSurf; 188 struct pipe_framebuffer_state fb; 189 const int srcW = abs(srcX1 - srcX0); 190 const int srcH = abs(srcY1 - srcY0); 191 const int srcLeft = MIN2(srcX0, srcX1); 192 const int srcTop = MIN2(srcY0, srcY1); 193 194 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 195 filter == PIPE_TEX_MIPFILTER_LINEAR); 196 197 if (srcLeft != srcX0) { 198 /* left-right flip */ 199 int tmp = dstX0; 200 dstX0 = dstX1; 201 dstX1 = tmp; 202 } 203 204 if (srcTop != srcY0) { 205 /* up-down flip */ 206 int tmp = dstY0; 207 dstY0 = dstY1; 208 dstY1 = tmp; 209 } 210 211 /* 212 * XXX for now we're always creating a temporary texture. 213 * Strictly speaking that's not always needed. 214 */ 215 216 /* create temp texture */ 217 memset(&texTemp, 0, sizeof(texTemp)); 218 texTemp.target = PIPE_TEXTURE_2D; 219 texTemp.format = src->format; 220 texTemp.last_level = 0; 221 texTemp.width[0] = srcW; 222 texTemp.height[0] = srcH; 223 texTemp.depth[0] = 1; 224 texTemp.compressed = 0; 225 texTemp.cpp = pf_get_bits(src->format) / 8; 226 227 tex = screen->texture_create(screen, &texTemp); 228 if (!tex) 229 return; 230 231 texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0); 232 233 /* load temp texture */ 234 pipe->surface_copy(pipe, FALSE, 235 texSurf, 0, 0, /* dest */ 236 src, srcLeft, srcTop, /* src */ 237 srcW, srcH); /* size */ 238 239 /* drawing dest */ 240 memset(&fb, 0, sizeof(fb)); 241 fb.num_cbufs = 1; 242 fb.cbufs[0] = dst; 243 pipe->set_framebuffer_state(pipe, &fb); 244 245 /* sampler */ 246 if (filter == PIPE_TEX_MIPFILTER_NEAREST) 247 pipe->bind_sampler_states(pipe, 1, &ctx->samplers[0]); 248 else 249 pipe->bind_sampler_states(pipe, 1, &ctx->samplers[1]); 250 251 /* texture */ 252 pipe->set_sampler_textures(pipe, 1, &tex); 253 254 /* shaders */ 255 pipe->bind_fs_state(pipe, ctx->fs); 256 pipe->bind_vs_state(pipe, ctx->vs); 257 258 /* misc state */ 259 pipe->bind_blend_state(pipe, ctx->blend); 260 pipe->bind_depth_stencil_alpha_state(pipe, ctx->depthstencil); 261 pipe->bind_rasterizer_state(pipe, ctx->rasterizer); 262 263 /* draw quad */ 264 util_draw_texquad(pipe, dstX0, dstY0, dstX1, dstY1, z); 265 266 /* unbind */ 267 pipe->set_sampler_textures(pipe, 0, NULL); 268 pipe->bind_sampler_states(pipe, 0, NULL); 269 270 /* free stuff */ 271 pipe_surface_reference(&texSurf, NULL); 272 screen->texture_release(screen, &tex); 273 274 /* Note: caller must restore pipe/gallium state at this time */ 275} 276 277