u_blitter.c revision cdc920a0
1/************************************************************************** 2 * 3 * Copyright 2009 Marek Olšák <maraeo@gmail.com> 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 **************************************************************************/ 26 27/** 28 * @file 29 * Blitter utility to facilitate acceleration of the clear, surface_copy, 30 * and surface_fill functions. 31 * 32 * @author Marek Olšák 33 */ 34 35#include "pipe/p_context.h" 36#include "pipe/p_defines.h" 37#include "util/u_inlines.h" 38#include "pipe/p_shader_tokens.h" 39#include "pipe/p_state.h" 40 41#include "util/u_format.h" 42#include "util/u_memory.h" 43#include "util/u_math.h" 44#include "util/u_blitter.h" 45#include "util/u_draw_quad.h" 46#include "util/u_pack_color.h" 47#include "util/u_rect.h" 48#include "util/u_simple_shaders.h" 49#include "util/u_texture.h" 50 51#define INVALID_PTR ((void*)~0) 52 53struct blitter_context_priv 54{ 55 struct blitter_context blitter; 56 57 struct pipe_context *pipe; /**< pipe context */ 58 struct pipe_buffer *vbuf; /**< quad */ 59 60 float vertices[4][2][4]; /**< {pos, color} or {pos, texcoord} */ 61 62 /* Templates for various state objects. */ 63 struct pipe_sampler_state template_sampler_state; 64 65 /* Constant state objects. */ 66 /* Vertex shaders. */ 67 void *vs_col; /**< Vertex shader which passes {pos, color} to the output */ 68 void *vs_tex; /**< Vertex shader which passes {pos, texcoord} to the output.*/ 69 70 /* Fragment shaders. */ 71 /* FS which outputs a color to multiple color buffers. */ 72 void *fs_col[PIPE_MAX_COLOR_BUFS]; 73 74 /* FS which outputs a color from a texture, 75 where the index is PIPE_TEXTURE_* to be sampled. */ 76 void *fs_texfetch_col[PIPE_MAX_TEXTURE_TYPES]; 77 78 /* FS which outputs a depth from a texture, 79 where the index is PIPE_TEXTURE_* to be sampled. */ 80 void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES]; 81 82 /* Blend state. */ 83 void *blend_write_color; /**< blend state with writemask of RGBA */ 84 void *blend_keep_color; /**< blend state with writemask of 0 */ 85 86 /* Depth stencil alpha state. */ 87 void *dsa_write_depth_stencil; 88 void *dsa_write_depth_keep_stencil; 89 void *dsa_keep_depth_stencil; 90 91 /* Sampler state for clamping to a miplevel. */ 92 void *sampler_state[PIPE_MAX_TEXTURE_LEVELS]; 93 94 /* Rasterizer state. */ 95 void *rs_state; 96 97 /* Viewport state. */ 98 struct pipe_viewport_state viewport; 99 100 /* Clip state. */ 101 struct pipe_clip_state clip; 102}; 103 104struct blitter_context *util_blitter_create(struct pipe_context *pipe) 105{ 106 struct blitter_context_priv *ctx; 107 struct pipe_blend_state blend = { 0 }; 108 struct pipe_depth_stencil_alpha_state dsa = { { 0 } }; 109 struct pipe_rasterizer_state rs_state = { 0 }; 110 struct pipe_sampler_state *sampler_state; 111 unsigned i; 112 113 ctx = CALLOC_STRUCT(blitter_context_priv); 114 if (!ctx) 115 return NULL; 116 117 ctx->pipe = pipe; 118 119 /* init state objects for them to be considered invalid */ 120 ctx->blitter.saved_blend_state = INVALID_PTR; 121 ctx->blitter.saved_dsa_state = INVALID_PTR; 122 ctx->blitter.saved_rs_state = INVALID_PTR; 123 ctx->blitter.saved_fs = INVALID_PTR; 124 ctx->blitter.saved_vs = INVALID_PTR; 125 ctx->blitter.saved_fb_state.nr_cbufs = ~0; 126 ctx->blitter.saved_num_textures = ~0; 127 ctx->blitter.saved_num_sampler_states = ~0; 128 129 /* blend state objects */ 130 ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend); 131 132 blend.rt[0].colormask = PIPE_MASK_RGBA; 133 ctx->blend_write_color = pipe->create_blend_state(pipe, &blend); 134 135 /* depth stencil alpha state objects */ 136 ctx->dsa_keep_depth_stencil = 137 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 138 139 dsa.depth.enabled = 1; 140 dsa.depth.writemask = 1; 141 dsa.depth.func = PIPE_FUNC_ALWAYS; 142 ctx->dsa_write_depth_keep_stencil = 143 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 144 145 dsa.stencil[0].enabled = 1; 146 dsa.stencil[0].func = PIPE_FUNC_ALWAYS; 147 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; 148 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; 149 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; 150 dsa.stencil[0].valuemask = 0xff; 151 dsa.stencil[0].writemask = 0xff; 152 ctx->dsa_write_depth_stencil = 153 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 154 /* The DSA state objects which write depth and stencil are created 155 * on-demand. */ 156 157 /* sampler state */ 158 sampler_state = &ctx->template_sampler_state; 159 sampler_state->wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 160 sampler_state->wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 161 sampler_state->wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 162 /* The sampler state objects which sample from a specified mipmap level 163 * are created on-demand. */ 164 165 /* rasterizer state */ 166 memset(&rs_state, 0, sizeof(rs_state)); 167 rs_state.front_winding = PIPE_WINDING_CW; 168 rs_state.cull_mode = PIPE_WINDING_NONE; 169 rs_state.gl_rasterization_rules = 1; 170 rs_state.flatshade = 1; 171 ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); 172 173 /* fragment shaders are created on-demand */ 174 175 /* vertex shaders */ 176 { 177 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, 178 TGSI_SEMANTIC_COLOR }; 179 const uint semantic_indices[] = { 0, 0 }; 180 ctx->vs_col = 181 util_make_vertex_passthrough_shader(pipe, 2, semantic_names, 182 semantic_indices); 183 } 184 { 185 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, 186 TGSI_SEMANTIC_GENERIC }; 187 const uint semantic_indices[] = { 0, 0 }; 188 ctx->vs_tex = 189 util_make_vertex_passthrough_shader(pipe, 2, semantic_names, 190 semantic_indices); 191 } 192 193 /* set invariant vertex coordinates */ 194 for (i = 0; i < 4; i++) 195 ctx->vertices[i][0][3] = 1; /*v.w*/ 196 197 /* create the vertex buffer */ 198 ctx->vbuf = pipe_buffer_create(ctx->pipe->screen, 199 32, 200 PIPE_BUFFER_USAGE_VERTEX, 201 sizeof(ctx->vertices)); 202 203 return &ctx->blitter; 204} 205 206void util_blitter_destroy(struct blitter_context *blitter) 207{ 208 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 209 struct pipe_context *pipe = ctx->pipe; 210 int i; 211 212 pipe->delete_blend_state(pipe, ctx->blend_write_color); 213 pipe->delete_blend_state(pipe, ctx->blend_keep_color); 214 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 215 pipe->delete_depth_stencil_alpha_state(pipe, 216 ctx->dsa_write_depth_keep_stencil); 217 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); 218 219 pipe->delete_rasterizer_state(pipe, ctx->rs_state); 220 pipe->delete_vs_state(pipe, ctx->vs_col); 221 pipe->delete_vs_state(pipe, ctx->vs_tex); 222 223 for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { 224 if (ctx->fs_texfetch_col[i]) 225 pipe->delete_fs_state(pipe, ctx->fs_texfetch_col[i]); 226 if (ctx->fs_texfetch_depth[i]) 227 pipe->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]); 228 } 229 230 for (i = 0; i < PIPE_MAX_COLOR_BUFS && ctx->fs_col[i]; i++) 231 if (ctx->fs_col[i]) 232 pipe->delete_fs_state(pipe, ctx->fs_col[i]); 233 234 for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++) 235 if (ctx->sampler_state[i]) 236 pipe->delete_sampler_state(pipe, ctx->sampler_state[i]); 237 238 pipe_buffer_reference(&ctx->vbuf, NULL); 239 FREE(ctx); 240} 241 242static void blitter_check_saved_CSOs(struct blitter_context_priv *ctx) 243{ 244 /* make sure these CSOs have been saved */ 245 assert(ctx->blitter.saved_blend_state != INVALID_PTR && 246 ctx->blitter.saved_dsa_state != INVALID_PTR && 247 ctx->blitter.saved_rs_state != INVALID_PTR && 248 ctx->blitter.saved_fs != INVALID_PTR && 249 ctx->blitter.saved_vs != INVALID_PTR); 250} 251 252static void blitter_restore_CSOs(struct blitter_context_priv *ctx) 253{ 254 struct pipe_context *pipe = ctx->pipe; 255 256 /* restore the state objects which are always required to be saved */ 257 pipe->bind_blend_state(pipe, ctx->blitter.saved_blend_state); 258 pipe->bind_depth_stencil_alpha_state(pipe, ctx->blitter.saved_dsa_state); 259 pipe->bind_rasterizer_state(pipe, ctx->blitter.saved_rs_state); 260 pipe->bind_fs_state(pipe, ctx->blitter.saved_fs); 261 pipe->bind_vs_state(pipe, ctx->blitter.saved_vs); 262 263 ctx->blitter.saved_blend_state = INVALID_PTR; 264 ctx->blitter.saved_dsa_state = INVALID_PTR; 265 ctx->blitter.saved_rs_state = INVALID_PTR; 266 ctx->blitter.saved_fs = INVALID_PTR; 267 ctx->blitter.saved_vs = INVALID_PTR; 268 269 pipe->set_stencil_ref(pipe, &ctx->blitter.saved_stencil_ref); 270 271 pipe->set_viewport_state(pipe, &ctx->blitter.saved_viewport); 272 pipe->set_clip_state(pipe, &ctx->blitter.saved_clip); 273 274 /* restore the state objects which are required to be saved before copy/fill 275 */ 276 if (ctx->blitter.saved_fb_state.nr_cbufs != ~0) { 277 pipe->set_framebuffer_state(pipe, &ctx->blitter.saved_fb_state); 278 ctx->blitter.saved_fb_state.nr_cbufs = ~0; 279 } 280 281 if (ctx->blitter.saved_num_sampler_states != ~0) { 282 pipe->bind_fragment_sampler_states(pipe, 283 ctx->blitter.saved_num_sampler_states, 284 ctx->blitter.saved_sampler_states); 285 ctx->blitter.saved_num_sampler_states = ~0; 286 } 287 288 if (ctx->blitter.saved_num_textures != ~0) { 289 pipe->set_fragment_sampler_textures(pipe, 290 ctx->blitter.saved_num_textures, 291 ctx->blitter.saved_textures); 292 ctx->blitter.saved_num_textures = ~0; 293 } 294} 295 296static void blitter_set_rectangle(struct blitter_context_priv *ctx, 297 unsigned x1, unsigned y1, 298 unsigned x2, unsigned y2, 299 unsigned width, unsigned height, 300 float depth) 301{ 302 int i; 303 304 /* set vertex positions */ 305 ctx->vertices[0][0][0] = (float)x1 / width * 2.0f - 1.0f; /*v0.x*/ 306 ctx->vertices[0][0][1] = (float)y1 / height * 2.0f - 1.0f; /*v0.y*/ 307 308 ctx->vertices[1][0][0] = (float)x2 / width * 2.0f - 1.0f; /*v1.x*/ 309 ctx->vertices[1][0][1] = (float)y1 / height * 2.0f - 1.0f; /*v1.y*/ 310 311 ctx->vertices[2][0][0] = (float)x2 / width * 2.0f - 1.0f; /*v2.x*/ 312 ctx->vertices[2][0][1] = (float)y2 / height * 2.0f - 1.0f; /*v2.y*/ 313 314 ctx->vertices[3][0][0] = (float)x1 / width * 2.0f - 1.0f; /*v3.x*/ 315 ctx->vertices[3][0][1] = (float)y2 / height * 2.0f - 1.0f; /*v3.y*/ 316 317 for (i = 0; i < 4; i++) 318 ctx->vertices[i][0][2] = depth; /*z*/ 319 320 /* viewport */ 321 ctx->viewport.scale[0] = 0.5f * width; 322 ctx->viewport.scale[1] = 0.5f * height; 323 ctx->viewport.scale[2] = 1.0f; 324 ctx->viewport.scale[3] = 1.0f; 325 ctx->viewport.translate[0] = 0.5f * width; 326 ctx->viewport.translate[1] = 0.5f * height; 327 ctx->viewport.translate[2] = 0.0f; 328 ctx->viewport.translate[3] = 0.0f; 329 ctx->pipe->set_viewport_state(ctx->pipe, &ctx->viewport); 330 331 /* clip */ 332 ctx->pipe->set_clip_state(ctx->pipe, &ctx->clip); 333} 334 335static void blitter_set_clear_color(struct blitter_context_priv *ctx, 336 const float *rgba) 337{ 338 int i; 339 340 for (i = 0; i < 4; i++) { 341 ctx->vertices[i][1][0] = rgba[0]; 342 ctx->vertices[i][1][1] = rgba[1]; 343 ctx->vertices[i][1][2] = rgba[2]; 344 ctx->vertices[i][1][3] = rgba[3]; 345 } 346} 347 348static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx, 349 struct pipe_surface *surf, 350 unsigned x1, unsigned y1, 351 unsigned x2, unsigned y2) 352{ 353 int i; 354 float s1 = x1 / (float)surf->width; 355 float t1 = y1 / (float)surf->height; 356 float s2 = x2 / (float)surf->width; 357 float t2 = y2 / (float)surf->height; 358 359 ctx->vertices[0][1][0] = s1; /*t0.s*/ 360 ctx->vertices[0][1][1] = t1; /*t0.t*/ 361 362 ctx->vertices[1][1][0] = s2; /*t1.s*/ 363 ctx->vertices[1][1][1] = t1; /*t1.t*/ 364 365 ctx->vertices[2][1][0] = s2; /*t2.s*/ 366 ctx->vertices[2][1][1] = t2; /*t2.t*/ 367 368 ctx->vertices[3][1][0] = s1; /*t3.s*/ 369 ctx->vertices[3][1][1] = t2; /*t3.t*/ 370 371 for (i = 0; i < 4; i++) { 372 ctx->vertices[i][1][2] = 0; /*r*/ 373 ctx->vertices[i][1][3] = 1; /*q*/ 374 } 375} 376 377static void blitter_set_texcoords_3d(struct blitter_context_priv *ctx, 378 struct pipe_surface *surf, 379 unsigned x1, unsigned y1, 380 unsigned x2, unsigned y2) 381{ 382 int i; 383 float depth = u_minify(surf->texture->depth0, surf->level); 384 float r = surf->zslice / depth; 385 386 blitter_set_texcoords_2d(ctx, surf, x1, y1, x2, y2); 387 388 for (i = 0; i < 4; i++) 389 ctx->vertices[i][1][2] = r; /*r*/ 390} 391 392static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx, 393 struct pipe_surface *surf, 394 unsigned x1, unsigned y1, 395 unsigned x2, unsigned y2) 396{ 397 int i; 398 float s1 = x1 / (float)surf->width; 399 float t1 = y1 / (float)surf->height; 400 float s2 = x2 / (float)surf->width; 401 float t2 = y2 / (float)surf->height; 402 float st[4][2]; 403 404 st[0][0] = s1; 405 st[0][1] = t1; 406 st[1][0] = s2; 407 st[1][1] = t1; 408 st[2][0] = s2; 409 st[2][1] = t2; 410 st[3][0] = s1; 411 st[3][1] = t2; 412 413 util_map_texcoords2d_onto_cubemap(surf->face, 414 /* pointer, stride in floats */ 415 &st[0][0], 2, 416 &ctx->vertices[0][1][0], 8); 417 418 for (i = 0; i < 4; i++) 419 ctx->vertices[i][1][3] = 1; /*q*/ 420} 421 422static void blitter_draw_quad(struct blitter_context_priv *ctx) 423{ 424 struct pipe_context *pipe = ctx->pipe; 425 426 /* write vertices and draw them */ 427 pipe_buffer_write(pipe->screen, ctx->vbuf, 428 0, sizeof(ctx->vertices), ctx->vertices); 429 430 util_draw_vertex_buffer(pipe, ctx->vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 431 4, /* verts */ 432 2); /* attribs/vert */ 433} 434 435static INLINE 436void **blitter_get_sampler_state(struct blitter_context_priv *ctx, 437 int miplevel) 438{ 439 struct pipe_context *pipe = ctx->pipe; 440 struct pipe_sampler_state *sampler_state = &ctx->template_sampler_state; 441 442 assert(miplevel < PIPE_MAX_TEXTURE_LEVELS); 443 444 /* Create the sampler state on-demand. */ 445 if (!ctx->sampler_state[miplevel]) { 446 sampler_state->lod_bias = miplevel; 447 sampler_state->min_lod = miplevel; 448 sampler_state->max_lod = miplevel; 449 450 ctx->sampler_state[miplevel] = pipe->create_sampler_state(pipe, 451 sampler_state); 452 } 453 454 /* Return void** so that it can be passed to bind_fragment_sampler_states 455 * directly. */ 456 return &ctx->sampler_state[miplevel]; 457} 458 459static INLINE 460void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs) 461{ 462 struct pipe_context *pipe = ctx->pipe; 463 unsigned index = num_cbufs ? num_cbufs - 1 : 0; 464 465 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); 466 467 if (!ctx->fs_col[index]) 468 ctx->fs_col[index] = 469 util_make_fragment_clonecolor_shader(pipe, num_cbufs); 470 471 return ctx->fs_col[index]; 472} 473 474static INLINE 475void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, 476 unsigned tex_target) 477{ 478 struct pipe_context *pipe = ctx->pipe; 479 480 assert(tex_target < PIPE_MAX_TEXTURE_TYPES); 481 482 /* Create the fragment shader on-demand. */ 483 if (!ctx->fs_texfetch_col[tex_target]) { 484 switch (tex_target) { 485 case PIPE_TEXTURE_1D: 486 ctx->fs_texfetch_col[PIPE_TEXTURE_1D] = 487 util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_1D); 488 break; 489 case PIPE_TEXTURE_2D: 490 ctx->fs_texfetch_col[PIPE_TEXTURE_2D] = 491 util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D); 492 break; 493 case PIPE_TEXTURE_3D: 494 ctx->fs_texfetch_col[PIPE_TEXTURE_3D] = 495 util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_3D); 496 break; 497 case PIPE_TEXTURE_CUBE: 498 ctx->fs_texfetch_col[PIPE_TEXTURE_CUBE] = 499 util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_CUBE); 500 break; 501 default:; 502 } 503 } 504 505 return ctx->fs_texfetch_col[tex_target]; 506} 507 508static INLINE 509void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx, 510 unsigned tex_target) 511{ 512 struct pipe_context *pipe = ctx->pipe; 513 514 assert(tex_target < PIPE_MAX_TEXTURE_TYPES); 515 516 /* Create the fragment shader on-demand. */ 517 if (!ctx->fs_texfetch_depth[tex_target]) { 518 switch (tex_target) { 519 case PIPE_TEXTURE_1D: 520 ctx->fs_texfetch_depth[PIPE_TEXTURE_1D] = 521 util_make_fragment_tex_shader_writedepth(pipe, TGSI_TEXTURE_1D); 522 break; 523 case PIPE_TEXTURE_2D: 524 ctx->fs_texfetch_depth[PIPE_TEXTURE_2D] = 525 util_make_fragment_tex_shader_writedepth(pipe, TGSI_TEXTURE_2D); 526 break; 527 case PIPE_TEXTURE_3D: 528 ctx->fs_texfetch_depth[PIPE_TEXTURE_3D] = 529 util_make_fragment_tex_shader_writedepth(pipe, TGSI_TEXTURE_3D); 530 break; 531 case PIPE_TEXTURE_CUBE: 532 ctx->fs_texfetch_depth[PIPE_TEXTURE_CUBE] = 533 util_make_fragment_tex_shader_writedepth(pipe,TGSI_TEXTURE_CUBE); 534 break; 535 default:; 536 } 537 } 538 539 return ctx->fs_texfetch_depth[tex_target]; 540} 541 542void util_blitter_clear(struct blitter_context *blitter, 543 unsigned width, unsigned height, 544 unsigned num_cbufs, 545 unsigned clear_buffers, 546 const float *rgba, 547 double depth, unsigned stencil) 548{ 549 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 550 struct pipe_context *pipe = ctx->pipe; 551 struct pipe_stencil_ref sr = { { 0 } }; 552 553 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); 554 555 blitter_check_saved_CSOs(ctx); 556 557 /* bind CSOs */ 558 if (clear_buffers & PIPE_CLEAR_COLOR) 559 pipe->bind_blend_state(pipe, ctx->blend_write_color); 560 else 561 pipe->bind_blend_state(pipe, ctx->blend_keep_color); 562 563 if (clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) { 564 sr.ref_value[0] = stencil & 0xff; 565 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); 566 pipe->set_stencil_ref(pipe, &sr); 567 } 568 else 569 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 570 571 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 572 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs)); 573 pipe->bind_vs_state(pipe, ctx->vs_col); 574 575 blitter_set_clear_color(ctx, rgba); 576 blitter_set_rectangle(ctx, 0, 0, width, height, width, height, depth); 577 blitter_draw_quad(ctx); 578 blitter_restore_CSOs(ctx); 579} 580 581static boolean 582is_overlap(unsigned sx1, unsigned sx2, unsigned sy1, unsigned sy2, 583 unsigned dx1, unsigned dx2, unsigned dy1, unsigned dy2) 584{ 585 if (sx1 >= dx2 || sx2 <= dx1 || sy1 >= dy2 || sy2 <= dy1) { 586 return FALSE; 587 } else { 588 return TRUE; 589 } 590} 591 592static void util_blitter_do_copy(struct blitter_context *blitter, 593 struct pipe_surface *dst, 594 unsigned dstx, unsigned dsty, 595 struct pipe_surface *src, 596 unsigned srcx, unsigned srcy, 597 unsigned width, unsigned height, 598 boolean is_depth) 599{ 600 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 601 struct pipe_context *pipe = ctx->pipe; 602 struct pipe_framebuffer_state fb_state; 603 604 assert(blitter->saved_fb_state.nr_cbufs != ~0); 605 assert(blitter->saved_num_textures != ~0); 606 assert(blitter->saved_num_sampler_states != ~0); 607 assert(src->texture->target < PIPE_MAX_TEXTURE_TYPES); 608 609 /* bind CSOs */ 610 fb_state.width = dst->width; 611 fb_state.height = dst->height; 612 613 if (is_depth) { 614 pipe->bind_blend_state(pipe, ctx->blend_keep_color); 615 pipe->bind_depth_stencil_alpha_state(pipe, 616 ctx->dsa_write_depth_keep_stencil); 617 pipe->bind_fs_state(pipe, 618 blitter_get_fs_texfetch_depth(ctx, src->texture->target)); 619 620 fb_state.nr_cbufs = 0; 621 fb_state.zsbuf = dst; 622 } else { 623 pipe->bind_blend_state(pipe, ctx->blend_write_color); 624 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 625 pipe->bind_fs_state(pipe, 626 blitter_get_fs_texfetch_col(ctx, src->texture->target)); 627 628 fb_state.nr_cbufs = 1; 629 fb_state.cbufs[0] = dst; 630 fb_state.zsbuf = 0; 631 } 632 633 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 634 pipe->bind_vs_state(pipe, ctx->vs_tex); 635 pipe->bind_fragment_sampler_states(pipe, 1, 636 blitter_get_sampler_state(ctx, src->level)); 637 pipe->set_fragment_sampler_textures(pipe, 1, &src->texture); 638 pipe->set_framebuffer_state(pipe, &fb_state); 639 640 /* set texture coordinates */ 641 switch (src->texture->target) { 642 case PIPE_TEXTURE_1D: 643 case PIPE_TEXTURE_2D: 644 blitter_set_texcoords_2d(ctx, src, srcx, srcy, 645 srcx+width, srcy+height); 646 break; 647 case PIPE_TEXTURE_3D: 648 blitter_set_texcoords_3d(ctx, src, srcx, srcy, 649 srcx+width, srcy+height); 650 break; 651 case PIPE_TEXTURE_CUBE: 652 blitter_set_texcoords_cube(ctx, src, srcx, srcy, 653 srcx+width, srcy+height); 654 break; 655 default: 656 assert(0); 657 } 658 659 blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, dst->width, dst->height, 0); 660 blitter_draw_quad(ctx); 661 662} 663 664static void util_blitter_overlap_copy(struct blitter_context *blitter, 665 struct pipe_surface *dst, 666 unsigned dstx, unsigned dsty, 667 struct pipe_surface *src, 668 unsigned srcx, unsigned srcy, 669 unsigned width, unsigned height) 670{ 671 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 672 struct pipe_context *pipe = ctx->pipe; 673 struct pipe_screen *screen = pipe->screen; 674 675 struct pipe_texture texTemp; 676 struct pipe_texture *texture; 677 struct pipe_surface *tex_surf; 678 679 /* check whether the states are properly saved */ 680 blitter_check_saved_CSOs(ctx); 681 682 memset(&texTemp, 0, sizeof(texTemp)); 683 texTemp.target = PIPE_TEXTURE_2D; 684 texTemp.format = dst->texture->format; /* XXX verify supported by driver! */ 685 texTemp.last_level = 0; 686 texTemp.width0 = width; 687 texTemp.height0 = height; 688 texTemp.depth0 = 1; 689 690 texture = screen->texture_create(screen, &texTemp); 691 if (!texture) 692 return; 693 694 tex_surf = screen->get_tex_surface(screen, texture, 0, 0, 0, 695 PIPE_BUFFER_USAGE_GPU_READ | 696 PIPE_BUFFER_USAGE_GPU_WRITE); 697 698 /* blit from the src to the temp */ 699 util_blitter_do_copy(blitter, tex_surf, 0, 0, 700 src, srcx, srcy, 701 width, height, 702 FALSE); 703 util_blitter_do_copy(blitter, dst, dstx, dsty, 704 tex_surf, 0, 0, 705 width, height, 706 FALSE); 707 pipe_surface_reference(&tex_surf, NULL); 708 pipe_texture_reference(&texture, NULL); 709 blitter_restore_CSOs(ctx); 710} 711 712void util_blitter_copy(struct blitter_context *blitter, 713 struct pipe_surface *dst, 714 unsigned dstx, unsigned dsty, 715 struct pipe_surface *src, 716 unsigned srcx, unsigned srcy, 717 unsigned width, unsigned height, 718 boolean ignore_stencil) 719{ 720 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 721 struct pipe_context *pipe = ctx->pipe; 722 struct pipe_screen *screen = pipe->screen; 723 boolean is_stencil, is_depth; 724 unsigned dst_tex_usage; 725 726 /* give up if textures are not set */ 727 assert(dst->texture && src->texture); 728 if (!dst->texture || !src->texture) 729 return; 730 731 if (dst->texture == src->texture) { 732 if (is_overlap(srcx, srcx + width, srcy, srcy + height, 733 dstx, dstx + width, dsty, dsty + height)) { 734 util_blitter_overlap_copy(blitter, dst, dstx, dsty, src, srcx, srcy, 735 width, height); 736 return; 737 } 738 } 739 740 is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0; 741 is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0; 742 dst_tex_usage = is_depth || is_stencil ? PIPE_TEXTURE_USAGE_DEPTH_STENCIL : 743 PIPE_TEXTURE_USAGE_RENDER_TARGET; 744 745 /* check if we can sample from and render to the surfaces */ 746 /* (assuming copying a stencil buffer is not possible) */ 747 if ((!ignore_stencil && is_stencil) || 748 !screen->is_format_supported(screen, dst->format, dst->texture->target, 749 dst_tex_usage, 0) || 750 !screen->is_format_supported(screen, src->format, src->texture->target, 751 PIPE_TEXTURE_USAGE_SAMPLER, 0)) { 752 util_surface_copy(pipe, FALSE, dst, dstx, dsty, src, srcx, srcy, 753 width, height); 754 return; 755 } 756 757 /* check whether the states are properly saved */ 758 blitter_check_saved_CSOs(ctx); 759 util_blitter_do_copy(blitter, 760 dst, dstx, dsty, 761 src, srcx, srcy, 762 width, height, is_depth); 763 blitter_restore_CSOs(ctx); 764} 765 766void util_blitter_fill(struct blitter_context *blitter, 767 struct pipe_surface *dst, 768 unsigned dstx, unsigned dsty, 769 unsigned width, unsigned height, 770 unsigned value) 771{ 772 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 773 struct pipe_context *pipe = ctx->pipe; 774 struct pipe_screen *screen = pipe->screen; 775 struct pipe_framebuffer_state fb_state; 776 float rgba[4]; 777 ubyte ub_rgba[4] = {0}; 778 union util_color color; 779 int i; 780 781 assert(dst->texture); 782 if (!dst->texture) 783 return; 784 785 /* check if we can render to the surface */ 786 if (util_format_is_depth_or_stencil(dst->format) || /* unlikely, but you never know */ 787 !screen->is_format_supported(screen, dst->format, dst->texture->target, 788 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { 789 util_surface_fill(pipe, dst, dstx, dsty, width, height, value); 790 return; 791 } 792 793 /* unpack the color */ 794 color.ui = value; 795 util_unpack_color_ub(dst->format, &color, 796 ub_rgba, ub_rgba+1, ub_rgba+2, ub_rgba+3); 797 for (i = 0; i < 4; i++) 798 rgba[i] = ubyte_to_float(ub_rgba[i]); 799 800 /* check the saved state */ 801 blitter_check_saved_CSOs(ctx); 802 assert(blitter->saved_fb_state.nr_cbufs != ~0); 803 804 /* bind CSOs */ 805 pipe->bind_blend_state(pipe, ctx->blend_write_color); 806 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 807 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 808 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1)); 809 pipe->bind_vs_state(pipe, ctx->vs_col); 810 811 /* set a framebuffer state */ 812 fb_state.width = dst->width; 813 fb_state.height = dst->height; 814 fb_state.nr_cbufs = 1; 815 fb_state.cbufs[0] = dst; 816 fb_state.zsbuf = 0; 817 pipe->set_framebuffer_state(pipe, &fb_state); 818 819 blitter_set_clear_color(ctx, rgba); 820 blitter_set_rectangle(ctx, 0, 0, width, height, dst->width, dst->height, 0); 821 blitter_draw_quad(ctx); 822 blitter_restore_CSOs(ctx); 823} 824