u_blit.c revision 9de26ccbcc2123b658c1b01c079b010473bc6da6
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 "util/u_debug.h" 38#include "pipe/p_defines.h" 39#include "pipe/p_inlines.h" 40#include "pipe/p_shader_tokens.h" 41#include "pipe/p_state.h" 42 43#include "util/u_blit.h" 44#include "util/u_draw_quad.h" 45#include "util/u_math.h" 46#include "util/u_memory.h" 47#include "util/u_simple_shaders.h" 48#include "util/u_surface.h" 49 50#include "cso_cache/cso_context.h" 51 52 53struct blit_state 54{ 55 struct pipe_context *pipe; 56 struct cso_context *cso; 57 58 struct pipe_blend_state blend; 59 struct pipe_depth_stencil_alpha_state depthstencil; 60 struct pipe_rasterizer_state rasterizer; 61 struct pipe_sampler_state sampler; 62 struct pipe_viewport_state viewport; 63 64 void *vs; 65 void *fs; 66 67 struct pipe_buffer *vbuf; /**< quad vertices */ 68 unsigned vbuf_slot; 69 70 float vertices[4][2][4]; /**< vertex/texcoords for quad */ 71}; 72 73 74/** 75 * Create state object for blit. 76 * Intended to be created once and re-used for many blit() calls. 77 */ 78struct blit_state * 79util_create_blit(struct pipe_context *pipe, struct cso_context *cso) 80{ 81 struct blit_state *ctx; 82 uint i; 83 84 ctx = CALLOC_STRUCT(blit_state); 85 if (!ctx) 86 return NULL; 87 88 ctx->pipe = pipe; 89 ctx->cso = cso; 90 91 /* disabled blending/masking */ 92 memset(&ctx->blend, 0, sizeof(ctx->blend)); 93 ctx->blend.colormask = PIPE_MASK_RGBA; 94 95 /* no-op depth/stencil/alpha */ 96 memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil)); 97 98 /* rasterizer */ 99 memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer)); 100 ctx->rasterizer.front_winding = PIPE_WINDING_CW; 101 ctx->rasterizer.cull_mode = PIPE_WINDING_NONE; 102 ctx->rasterizer.bypass_vs_clip_and_viewport = 1; 103 ctx->rasterizer.gl_rasterization_rules = 1; 104 105 /* samplers */ 106 memset(&ctx->sampler, 0, sizeof(ctx->sampler)); 107 ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 108 ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 109 ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 110 ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 111 ctx->sampler.min_img_filter = 0; /* set later */ 112 ctx->sampler.mag_img_filter = 0; /* set later */ 113 ctx->sampler.normalized_coords = 1; 114 115 116 /* vertex shader - still required to provide the linkage between 117 * fragment shader input semantics and vertex_element/buffers. 118 */ 119 { 120 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, 121 TGSI_SEMANTIC_GENERIC }; 122 const uint semantic_indexes[] = { 0, 0 }; 123 ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names, 124 semantic_indexes); 125 } 126 127 /* fragment shader */ 128 ctx->fs = util_make_fragment_tex_shader(pipe); 129 ctx->vbuf = NULL; 130 131 /* init vertex data that doesn't change */ 132 for (i = 0; i < 4; i++) { 133 ctx->vertices[i][0][3] = 1.0f; /* w */ 134 ctx->vertices[i][1][2] = 0.0f; /* r */ 135 ctx->vertices[i][1][3] = 1.0f; /* q */ 136 } 137 138 return ctx; 139} 140 141 142/** 143 * Destroy a blit context 144 */ 145void 146util_destroy_blit(struct blit_state *ctx) 147{ 148 struct pipe_context *pipe = ctx->pipe; 149 150 pipe->delete_vs_state(pipe, ctx->vs); 151 pipe->delete_fs_state(pipe, ctx->fs); 152 153 pipe_buffer_reference(&ctx->vbuf, NULL); 154 155 FREE(ctx); 156} 157 158 159/** 160 * Get offset of next free slot in vertex buffer for quad vertices. 161 */ 162static unsigned 163get_next_slot( struct blit_state *ctx ) 164{ 165 const unsigned max_slots = 4096 / sizeof ctx->vertices; 166 167 if (ctx->vbuf_slot >= max_slots) 168 util_blit_flush( ctx ); 169 170 if (!ctx->vbuf) { 171 ctx->vbuf = pipe_buffer_create(ctx->pipe->screen, 172 32, 173 PIPE_BUFFER_USAGE_VERTEX, 174 max_slots * sizeof ctx->vertices); 175 } 176 177 return ctx->vbuf_slot++ * sizeof ctx->vertices; 178} 179 180 181/** 182 * Setup vertex data for the textured quad we'll draw. 183 * Note: y=0=top 184 */ 185static unsigned 186setup_vertex_data(struct blit_state *ctx, 187 float x0, float y0, float x1, float y1, float z) 188{ 189 unsigned offset; 190 191 ctx->vertices[0][0][0] = x0; 192 ctx->vertices[0][0][1] = y0; 193 ctx->vertices[0][0][2] = z; 194 ctx->vertices[0][1][0] = 0.0f; /*s*/ 195 ctx->vertices[0][1][1] = 0.0f; /*t*/ 196 197 ctx->vertices[1][0][0] = x1; 198 ctx->vertices[1][0][1] = y0; 199 ctx->vertices[1][0][2] = z; 200 ctx->vertices[1][1][0] = 1.0f; /*s*/ 201 ctx->vertices[1][1][1] = 0.0f; /*t*/ 202 203 ctx->vertices[2][0][0] = x1; 204 ctx->vertices[2][0][1] = y1; 205 ctx->vertices[2][0][2] = z; 206 ctx->vertices[2][1][0] = 1.0f; 207 ctx->vertices[2][1][1] = 1.0f; 208 209 ctx->vertices[3][0][0] = x0; 210 ctx->vertices[3][0][1] = y1; 211 ctx->vertices[3][0][2] = z; 212 ctx->vertices[3][1][0] = 0.0f; 213 ctx->vertices[3][1][1] = 1.0f; 214 215 offset = get_next_slot( ctx ); 216 217 pipe_buffer_write(ctx->pipe->screen, ctx->vbuf, 218 offset, sizeof(ctx->vertices), ctx->vertices); 219 220 return offset; 221} 222 223 224/** 225 * Setup vertex data for the textured quad we'll draw. 226 * Note: y=0=top 227 */ 228static unsigned 229setup_vertex_data_tex(struct blit_state *ctx, 230 float x0, float y0, float x1, float y1, 231 float s0, float t0, float s1, float t1, 232 float z) 233{ 234 unsigned offset; 235 236 ctx->vertices[0][0][0] = x0; 237 ctx->vertices[0][0][1] = y0; 238 ctx->vertices[0][0][2] = z; 239 ctx->vertices[0][1][0] = s0; /*s*/ 240 ctx->vertices[0][1][1] = t0; /*t*/ 241 242 ctx->vertices[1][0][0] = x1; 243 ctx->vertices[1][0][1] = y0; 244 ctx->vertices[1][0][2] = z; 245 ctx->vertices[1][1][0] = s1; /*s*/ 246 ctx->vertices[1][1][1] = t0; /*t*/ 247 248 ctx->vertices[2][0][0] = x1; 249 ctx->vertices[2][0][1] = y1; 250 ctx->vertices[2][0][2] = z; 251 ctx->vertices[2][1][0] = s1; 252 ctx->vertices[2][1][1] = t1; 253 254 ctx->vertices[3][0][0] = x0; 255 ctx->vertices[3][0][1] = y1; 256 ctx->vertices[3][0][2] = z; 257 ctx->vertices[3][1][0] = s0; 258 ctx->vertices[3][1][1] = t1; 259 260 offset = get_next_slot( ctx ); 261 262 pipe_buffer_write(ctx->pipe->screen, ctx->vbuf, 263 offset, sizeof(ctx->vertices), ctx->vertices); 264 265 return offset; 266} 267 268 269/** 270 * \return TRUE if two regions overlap, FALSE otherwise 271 */ 272static boolean 273regions_overlap(int srcX0, int srcY0, 274 int srcX1, int srcY1, 275 int dstX0, int dstY0, 276 int dstX1, int dstY1) 277{ 278 if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1)) 279 return FALSE; /* src completely left of dst */ 280 281 if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1)) 282 return FALSE; /* dst completely left of src */ 283 284 if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1)) 285 return FALSE; /* src completely above dst */ 286 287 if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1)) 288 return FALSE; /* dst completely above src */ 289 290 return TRUE; /* some overlap */ 291} 292 293 294/** 295 * Copy pixel block from src surface to dst surface. 296 * Overlapping regions are acceptable. 297 * Flipping and stretching are supported. 298 * XXX what about clipping??? 299 * XXX need some control over blitting Z and/or stencil. 300 */ 301void 302util_blit_pixels(struct blit_state *ctx, 303 struct pipe_surface *src, 304 int srcX0, int srcY0, 305 int srcX1, int srcY1, 306 struct pipe_surface *dst, 307 int dstX0, int dstY0, 308 int dstX1, int dstY1, 309 float z, uint filter) 310{ 311 struct pipe_context *pipe = ctx->pipe; 312 struct pipe_screen *screen = pipe->screen; 313 struct pipe_texture texTemp, *tex; 314 struct pipe_surface *texSurf; 315 struct pipe_framebuffer_state fb; 316 const int srcW = abs(srcX1 - srcX0); 317 const int srcH = abs(srcY1 - srcY0); 318 const int srcLeft = MIN2(srcX0, srcX1); 319 const int srcTop = MIN2(srcY0, srcY1); 320 unsigned offset; 321 boolean overlap; 322 323 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 324 filter == PIPE_TEX_MIPFILTER_LINEAR); 325 326 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, 327 PIPE_TEXTURE_USAGE_SAMPLER, 0)); 328 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 329 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); 330 331 /* do the regions overlap? */ 332 overlap = util_same_surface(src, dst) && 333 regions_overlap(srcX0, srcY0, srcX1, srcY1, 334 dstX0, dstY0, dstX1, dstY1); 335 336 /* 337 * Check for simple case: no format conversion, no flipping, no stretching, 338 * no overlapping. 339 * Filter mode should not matter since there's no stretching. 340 */ 341 if (dst->format == src->format && 342 srcX0 < srcX1 && 343 dstX0 < dstX1 && 344 srcY0 < srcY1 && 345 dstY0 < dstY1 && 346 (dstX1 - dstX0) == (srcX1 - srcX0) && 347 (dstY1 - dstY0) == (srcY1 - srcY0) && 348 !overlap) { 349 pipe->surface_copy(pipe, 350 dst, dstX0, dstY0, /* dest */ 351 src, srcX0, srcY0, /* src */ 352 srcW, srcH); /* size */ 353 return; 354 } 355 356 if (srcLeft != srcX0) { 357 /* left-right flip */ 358 int tmp = dstX0; 359 dstX0 = dstX1; 360 dstX1 = tmp; 361 } 362 363 if (srcTop != srcY0) { 364 /* up-down flip */ 365 int tmp = dstY0; 366 dstY0 = dstY1; 367 dstY1 = tmp; 368 } 369 370 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 371 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); 372 373 /* 374 * XXX for now we're always creating a temporary texture. 375 * Strictly speaking that's not always needed. 376 */ 377 378 /* create temp texture */ 379 memset(&texTemp, 0, sizeof(texTemp)); 380 texTemp.target = PIPE_TEXTURE_2D; 381 texTemp.format = src->format; 382 texTemp.last_level = 0; 383 texTemp.width[0] = srcW; 384 texTemp.height[0] = srcH; 385 texTemp.depth[0] = 1; 386 pf_get_block(src->format, &texTemp.block); 387 388 tex = screen->texture_create(screen, &texTemp); 389 if (!tex) 390 return; 391 392 texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, 393 PIPE_BUFFER_USAGE_GPU_WRITE); 394 395 /* load temp texture */ 396 pipe->surface_copy(pipe, 397 texSurf, 0, 0, /* dest */ 398 src, srcLeft, srcTop, /* src */ 399 srcW, srcH); /* size */ 400 401 /* free the surface, update the texture if necessary. 402 */ 403 pipe_surface_reference(&texSurf, NULL); 404 405 /* save state (restored below) */ 406 cso_save_blend(ctx->cso); 407 cso_save_depth_stencil_alpha(ctx->cso); 408 cso_save_rasterizer(ctx->cso); 409 cso_save_samplers(ctx->cso); 410 cso_save_sampler_textures(ctx->cso); 411 cso_save_framebuffer(ctx->cso); 412 cso_save_fragment_shader(ctx->cso); 413 cso_save_vertex_shader(ctx->cso); 414 415 /* set misc state we care about */ 416 cso_set_blend(ctx->cso, &ctx->blend); 417 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); 418 cso_set_rasterizer(ctx->cso, &ctx->rasterizer); 419 420 /* sampler */ 421 ctx->sampler.min_img_filter = filter; 422 ctx->sampler.mag_img_filter = filter; 423 cso_single_sampler(ctx->cso, 0, &ctx->sampler); 424 cso_single_sampler_done(ctx->cso); 425 426 /* texture */ 427 cso_set_sampler_textures(ctx->cso, 1, &tex); 428 429 /* shaders */ 430 cso_set_fragment_shader_handle(ctx->cso, ctx->fs); 431 cso_set_vertex_shader_handle(ctx->cso, ctx->vs); 432 433 /* drawing dest */ 434 memset(&fb, 0, sizeof(fb)); 435 fb.width = dst->width; 436 fb.height = dst->height; 437 fb.nr_cbufs = 1; 438 fb.cbufs[0] = dst; 439 cso_set_framebuffer(ctx->cso, &fb); 440 441 /* draw quad */ 442 offset = setup_vertex_data(ctx, 443 (float) dstX0, (float) dstY0, 444 (float) dstX1, (float) dstY1, z); 445 446 util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, offset, 447 PIPE_PRIM_TRIANGLE_FAN, 448 4, /* verts */ 449 2); /* attribs/vert */ 450 451 /* restore state we changed */ 452 cso_restore_blend(ctx->cso); 453 cso_restore_depth_stencil_alpha(ctx->cso); 454 cso_restore_rasterizer(ctx->cso); 455 cso_restore_samplers(ctx->cso); 456 cso_restore_sampler_textures(ctx->cso); 457 cso_restore_framebuffer(ctx->cso); 458 cso_restore_fragment_shader(ctx->cso); 459 cso_restore_vertex_shader(ctx->cso); 460 461 pipe_texture_reference(&tex, NULL); 462} 463 464 465/* Release vertex buffer at end of frame to avoid synchronous 466 * rendering. 467 */ 468void util_blit_flush( struct blit_state *ctx ) 469{ 470 pipe_buffer_reference(&ctx->vbuf, NULL); 471 ctx->vbuf_slot = 0; 472} 473 474 475 476/** 477 * Copy pixel block from src texture to dst surface. 478 * Overlapping regions are acceptable. 479 * 480 * XXX Should support selection of level. 481 * XXX need some control over blitting Z and/or stencil. 482 */ 483void 484util_blit_pixels_tex(struct blit_state *ctx, 485 struct pipe_texture *tex, 486 int srcX0, int srcY0, 487 int srcX1, int srcY1, 488 struct pipe_surface *dst, 489 int dstX0, int dstY0, 490 int dstX1, int dstY1, 491 float z, uint filter) 492{ 493 struct pipe_framebuffer_state fb; 494 float s0, t0, s1, t1; 495 unsigned offset; 496 497 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 498 filter == PIPE_TEX_MIPFILTER_LINEAR); 499 500 assert(tex->width[0] != 0); 501 assert(tex->height[0] != 0); 502 503 s0 = srcX0 / (float)tex->width[0]; 504 s1 = srcX1 / (float)tex->width[0]; 505 t0 = srcY0 / (float)tex->height[0]; 506 t1 = srcY1 / (float)tex->height[0]; 507 508 assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format, 509 PIPE_TEXTURE_2D, 510 PIPE_TEXTURE_USAGE_RENDER_TARGET, 511 0)); 512 513 /* save state (restored below) */ 514 cso_save_blend(ctx->cso); 515 cso_save_depth_stencil_alpha(ctx->cso); 516 cso_save_rasterizer(ctx->cso); 517 cso_save_samplers(ctx->cso); 518 cso_save_sampler_textures(ctx->cso); 519 cso_save_framebuffer(ctx->cso); 520 cso_save_fragment_shader(ctx->cso); 521 cso_save_vertex_shader(ctx->cso); 522 523 /* set misc state we care about */ 524 cso_set_blend(ctx->cso, &ctx->blend); 525 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); 526 cso_set_rasterizer(ctx->cso, &ctx->rasterizer); 527 528 /* sampler */ 529 ctx->sampler.min_img_filter = filter; 530 ctx->sampler.mag_img_filter = filter; 531 cso_single_sampler(ctx->cso, 0, &ctx->sampler); 532 cso_single_sampler_done(ctx->cso); 533 534 /* texture */ 535 cso_set_sampler_textures(ctx->cso, 1, &tex); 536 537 /* shaders */ 538 cso_set_fragment_shader_handle(ctx->cso, ctx->fs); 539 cso_set_vertex_shader_handle(ctx->cso, ctx->vs); 540 541 /* drawing dest */ 542 memset(&fb, 0, sizeof(fb)); 543 fb.width = dst->width; 544 fb.height = dst->height; 545 fb.nr_cbufs = 1; 546 fb.cbufs[0] = dst; 547 cso_set_framebuffer(ctx->cso, &fb); 548 549 /* draw quad */ 550 offset = setup_vertex_data_tex(ctx, 551 (float) dstX0, (float) dstY0, 552 (float) dstX1, (float) dstY1, 553 s0, t0, s1, t1, 554 z); 555 556 util_draw_vertex_buffer(ctx->pipe, 557 ctx->vbuf, offset, 558 PIPE_PRIM_TRIANGLE_FAN, 559 4, /* verts */ 560 2); /* attribs/vert */ 561 562 /* restore state we changed */ 563 cso_restore_blend(ctx->cso); 564 cso_restore_depth_stencil_alpha(ctx->cso); 565 cso_restore_rasterizer(ctx->cso); 566 cso_restore_samplers(ctx->cso); 567 cso_restore_sampler_textures(ctx->cso); 568 cso_restore_framebuffer(ctx->cso); 569 cso_restore_fragment_shader(ctx->cso); 570 cso_restore_vertex_shader(ctx->cso); 571} 572