u_blitter.c revision c12c05c198f1cfd63eb52eeeb3c6e22dcb169b32
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, clear_render_target, 30 * clear_depth_stencil, and resource_copy_region 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_sampler.h" 47#include "util/u_simple_shaders.h" 48#include "util/u_surface.h" 49#include "util/u_texture.h" 50 51#define INVALID_PTR ((void*)~0) 52 53struct blitter_context_priv 54{ 55 struct blitter_context base; 56 57 struct pipe_resource *vbuf; /**< quad */ 58 59 float vertices[4][2][4]; /**< {pos, color} or {pos, texcoord} */ 60 61 /* Templates for various state objects. */ 62 struct pipe_sampler_state template_sampler_state; 63 64 /* Constant state objects. */ 65 /* Vertex shaders. */ 66 void *vs; /**< Vertex shader which passes {pos, generic} to the output.*/ 67 68 /* Fragment shaders. */ 69 /* The shader at index i outputs color to color buffers 0,1,...,i-1. */ 70 void *fs_col[PIPE_MAX_COLOR_BUFS+1]; 71 72 /* FS which outputs a color from a texture, 73 where the index is PIPE_TEXTURE_* to be sampled. */ 74 void *fs_texfetch_col[PIPE_MAX_TEXTURE_TYPES]; 75 76 /* FS which outputs a depth from a texture, 77 where the index is PIPE_TEXTURE_* to be sampled. */ 78 void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES]; 79 80 /* Blend state. */ 81 void *blend_write_color; /**< blend state with writemask of RGBA */ 82 void *blend_keep_color; /**< blend state with writemask of 0 */ 83 84 /* Depth stencil alpha state. */ 85 void *dsa_write_depth_stencil; 86 void *dsa_write_depth_keep_stencil; 87 void *dsa_keep_depth_stencil; 88 void *dsa_keep_depth_write_stencil; 89 90 void *velem_state; 91 92 /* Sampler state for clamping to a miplevel. */ 93 void *sampler_state[PIPE_MAX_TEXTURE_LEVELS * 2]; 94 95 /* Rasterizer state. */ 96 void *rs_state; 97 98 /* Viewport state. */ 99 struct pipe_viewport_state viewport; 100 101 /* Clip state. */ 102 struct pipe_clip_state clip; 103 104 /* Destination surface dimensions. */ 105 unsigned dst_width; 106 unsigned dst_height; 107}; 108 109static void blitter_draw_rectangle(struct blitter_context *blitter, 110 unsigned x, unsigned y, 111 unsigned width, unsigned height, 112 float depth, 113 enum blitter_attrib_type type, 114 const union pipe_color_union *attrib); 115 116 117struct blitter_context *util_blitter_create(struct pipe_context *pipe) 118{ 119 struct blitter_context_priv *ctx; 120 struct pipe_blend_state blend; 121 struct pipe_depth_stencil_alpha_state dsa; 122 struct pipe_rasterizer_state rs_state; 123 struct pipe_sampler_state *sampler_state; 124 struct pipe_vertex_element velem[2]; 125 unsigned i; 126 127 ctx = CALLOC_STRUCT(blitter_context_priv); 128 if (!ctx) 129 return NULL; 130 131 ctx->base.pipe = pipe; 132 ctx->base.draw_rectangle = blitter_draw_rectangle; 133 134 /* init state objects for them to be considered invalid */ 135 ctx->base.saved_blend_state = INVALID_PTR; 136 ctx->base.saved_dsa_state = INVALID_PTR; 137 ctx->base.saved_rs_state = INVALID_PTR; 138 ctx->base.saved_fs = INVALID_PTR; 139 ctx->base.saved_vs = INVALID_PTR; 140 ctx->base.saved_velem_state = INVALID_PTR; 141 ctx->base.saved_fb_state.nr_cbufs = ~0; 142 ctx->base.saved_num_sampler_views = ~0; 143 ctx->base.saved_num_sampler_states = ~0; 144 ctx->base.saved_num_vertex_buffers = ~0; 145 146 /* blend state objects */ 147 memset(&blend, 0, sizeof(blend)); 148 ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend); 149 150 blend.rt[0].colormask = PIPE_MASK_RGBA; 151 ctx->blend_write_color = pipe->create_blend_state(pipe, &blend); 152 153 /* depth stencil alpha state objects */ 154 memset(&dsa, 0, sizeof(dsa)); 155 ctx->dsa_keep_depth_stencil = 156 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 157 158 dsa.depth.enabled = 1; 159 dsa.depth.writemask = 1; 160 dsa.depth.func = PIPE_FUNC_ALWAYS; 161 ctx->dsa_write_depth_keep_stencil = 162 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 163 164 dsa.stencil[0].enabled = 1; 165 dsa.stencil[0].func = PIPE_FUNC_ALWAYS; 166 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; 167 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; 168 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; 169 dsa.stencil[0].valuemask = 0xff; 170 dsa.stencil[0].writemask = 0xff; 171 ctx->dsa_write_depth_stencil = 172 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 173 174 175 dsa.depth.enabled = 0; 176 dsa.depth.writemask = 0; 177 ctx->dsa_keep_depth_write_stencil = 178 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 179 180 /* sampler state */ 181 sampler_state = &ctx->template_sampler_state; 182 sampler_state->wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 183 sampler_state->wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 184 sampler_state->wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 185 sampler_state->normalized_coords = TRUE; 186 /* The sampler state objects which sample from a specified mipmap level 187 * are created on-demand. */ 188 189 /* rasterizer state */ 190 memset(&rs_state, 0, sizeof(rs_state)); 191 rs_state.cull_face = PIPE_FACE_NONE; 192 rs_state.gl_rasterization_rules = 1; 193 rs_state.flatshade = 1; 194 ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); 195 196 /* vertex elements state */ 197 memset(&velem[0], 0, sizeof(velem[0]) * 2); 198 for (i = 0; i < 2; i++) { 199 velem[i].src_offset = i * 4 * sizeof(float); 200 velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 201 } 202 ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]); 203 204 /* fragment shaders are created on-demand */ 205 206 /* vertex shader */ 207 { 208 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, 209 TGSI_SEMANTIC_GENERIC }; 210 const uint semantic_indices[] = { 0, 0 }; 211 ctx->vs = 212 util_make_vertex_passthrough_shader(pipe, 2, semantic_names, 213 semantic_indices); 214 } 215 216 /* set invariant vertex coordinates */ 217 for (i = 0; i < 4; i++) 218 ctx->vertices[i][0][3] = 1; /*v.w*/ 219 220 /* create the vertex buffer */ 221 ctx->vbuf = pipe_user_buffer_create(ctx->base.pipe->screen, 222 ctx->vertices, 223 sizeof(ctx->vertices), 224 PIPE_BIND_VERTEX_BUFFER); 225 226 return &ctx->base; 227} 228 229void util_blitter_destroy(struct blitter_context *blitter) 230{ 231 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 232 struct pipe_context *pipe = blitter->pipe; 233 int i; 234 235 pipe->delete_blend_state(pipe, ctx->blend_write_color); 236 pipe->delete_blend_state(pipe, ctx->blend_keep_color); 237 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 238 pipe->delete_depth_stencil_alpha_state(pipe, 239 ctx->dsa_write_depth_keep_stencil); 240 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); 241 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); 242 243 pipe->delete_rasterizer_state(pipe, ctx->rs_state); 244 pipe->delete_vs_state(pipe, ctx->vs); 245 pipe->delete_vertex_elements_state(pipe, ctx->velem_state); 246 247 for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { 248 if (ctx->fs_texfetch_col[i]) 249 pipe->delete_fs_state(pipe, ctx->fs_texfetch_col[i]); 250 if (ctx->fs_texfetch_depth[i]) 251 pipe->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]); 252 } 253 254 for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++) 255 if (ctx->fs_col[i]) 256 pipe->delete_fs_state(pipe, ctx->fs_col[i]); 257 258 for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS * 2; i++) 259 if (ctx->sampler_state[i]) 260 pipe->delete_sampler_state(pipe, ctx->sampler_state[i]); 261 262 pipe_resource_reference(&ctx->vbuf, NULL); 263 FREE(ctx); 264} 265 266static void blitter_set_running_flag(struct blitter_context_priv *ctx) 267{ 268 if (ctx->base.running) { 269 _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n", 270 __LINE__); 271 } 272 ctx->base.running = TRUE; 273} 274 275static void blitter_unset_running_flag(struct blitter_context_priv *ctx) 276{ 277 if (!ctx->base.running) { 278 _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n", 279 __LINE__); 280 } 281 ctx->base.running = FALSE; 282} 283 284static void blitter_check_saved_vertex_states(struct blitter_context_priv *ctx) 285{ 286 assert(ctx->base.saved_num_vertex_buffers != ~0 && 287 ctx->base.saved_velem_state != INVALID_PTR && 288 ctx->base.saved_vs != INVALID_PTR && 289 ctx->base.saved_rs_state != INVALID_PTR); 290} 291 292static void blitter_restore_vertex_states(struct blitter_context_priv *ctx) 293{ 294 struct pipe_context *pipe = ctx->base.pipe; 295 unsigned i; 296 297 /* Vertex buffers. */ 298 pipe->set_vertex_buffers(pipe, 299 ctx->base.saved_num_vertex_buffers, 300 ctx->base.saved_vertex_buffers); 301 302 for (i = 0; i < ctx->base.saved_num_vertex_buffers; i++) { 303 if (ctx->base.saved_vertex_buffers[i].buffer) { 304 pipe_resource_reference(&ctx->base.saved_vertex_buffers[i].buffer, 305 NULL); 306 } 307 } 308 ctx->base.saved_num_vertex_buffers = ~0; 309 310 /* Vertex elements. */ 311 pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state); 312 ctx->base.saved_velem_state = INVALID_PTR; 313 314 /* Vertex shader. */ 315 pipe->bind_vs_state(pipe, ctx->base.saved_vs); 316 ctx->base.saved_vs = INVALID_PTR; 317 318 319 /* Rasterizer. */ 320 pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state); 321 ctx->base.saved_rs_state = INVALID_PTR; 322} 323 324static void blitter_check_saved_fragment_states(struct blitter_context_priv *ctx) 325{ 326 assert(ctx->base.saved_fs != INVALID_PTR && 327 ctx->base.saved_dsa_state != INVALID_PTR && 328 ctx->base.saved_blend_state != INVALID_PTR); 329} 330 331static void blitter_restore_fragment_states(struct blitter_context_priv *ctx) 332{ 333 struct pipe_context *pipe = ctx->base.pipe; 334 335 /* Fragment shader. */ 336 pipe->bind_fs_state(pipe, ctx->base.saved_fs); 337 ctx->base.saved_fs = INVALID_PTR; 338 339 /* Depth, stencil, alpha. */ 340 pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state); 341 ctx->base.saved_dsa_state = INVALID_PTR; 342 343 /* Blend state. */ 344 pipe->bind_blend_state(pipe, ctx->base.saved_blend_state); 345 ctx->base.saved_blend_state = INVALID_PTR; 346 347 /* Miscellaneous states. */ 348 /* XXX check whether these are saved and whether they need to be restored 349 * (depending on the operation) */ 350 pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref); 351 pipe->set_viewport_state(pipe, &ctx->base.saved_viewport); 352 pipe->set_clip_state(pipe, &ctx->base.saved_clip); 353} 354 355static void blitter_check_saved_fb_state(struct blitter_context_priv *ctx) 356{ 357 assert(ctx->base.saved_fb_state.nr_cbufs != ~0); 358} 359 360static void blitter_restore_fb_state(struct blitter_context_priv *ctx) 361{ 362 struct pipe_context *pipe = ctx->base.pipe; 363 364 pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state); 365 util_unreference_framebuffer_state(&ctx->base.saved_fb_state); 366} 367 368static void blitter_check_saved_textures(struct blitter_context_priv *ctx) 369{ 370 assert(ctx->base.saved_num_sampler_states != ~0 && 371 ctx->base.saved_num_sampler_views != ~0); 372} 373 374static void blitter_restore_textures(struct blitter_context_priv *ctx) 375{ 376 struct pipe_context *pipe = ctx->base.pipe; 377 unsigned i; 378 379 /* Fragment sampler states. */ 380 pipe->bind_fragment_sampler_states(pipe, 381 ctx->base.saved_num_sampler_states, 382 ctx->base.saved_sampler_states); 383 ctx->base.saved_num_sampler_states = ~0; 384 385 /* Fragment sampler views. */ 386 pipe->set_fragment_sampler_views(pipe, 387 ctx->base.saved_num_sampler_views, 388 ctx->base.saved_sampler_views); 389 390 for (i = 0; i < ctx->base.saved_num_sampler_views; i++) 391 pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i], NULL); 392 393 ctx->base.saved_num_sampler_views = ~0; 394} 395 396static void blitter_set_rectangle(struct blitter_context_priv *ctx, 397 unsigned x1, unsigned y1, 398 unsigned x2, unsigned y2, 399 float depth) 400{ 401 int i; 402 403 /* set vertex positions */ 404 ctx->vertices[0][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v0.x*/ 405 ctx->vertices[0][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v0.y*/ 406 407 ctx->vertices[1][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v1.x*/ 408 ctx->vertices[1][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v1.y*/ 409 410 ctx->vertices[2][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v2.x*/ 411 ctx->vertices[2][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v2.y*/ 412 413 ctx->vertices[3][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v3.x*/ 414 ctx->vertices[3][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v3.y*/ 415 416 for (i = 0; i < 4; i++) 417 ctx->vertices[i][0][2] = depth; /*z*/ 418 419 /* viewport */ 420 ctx->viewport.scale[0] = 0.5f * ctx->dst_width; 421 ctx->viewport.scale[1] = 0.5f * ctx->dst_height; 422 ctx->viewport.scale[2] = 1.0f; 423 ctx->viewport.scale[3] = 1.0f; 424 ctx->viewport.translate[0] = 0.5f * ctx->dst_width; 425 ctx->viewport.translate[1] = 0.5f * ctx->dst_height; 426 ctx->viewport.translate[2] = 0.0f; 427 ctx->viewport.translate[3] = 0.0f; 428 ctx->base.pipe->set_viewport_state(ctx->base.pipe, &ctx->viewport); 429 430 /* clip */ 431 ctx->base.pipe->set_clip_state(ctx->base.pipe, &ctx->clip); 432} 433 434static void blitter_set_clear_color(struct blitter_context_priv *ctx, 435 const union pipe_color_union *color) 436{ 437 int i; 438 439 if (color) { 440 for (i = 0; i < 4; i++) { 441 ctx->vertices[i][1][0] = color->f[0]; 442 ctx->vertices[i][1][1] = color->f[1]; 443 ctx->vertices[i][1][2] = color->f[2]; 444 ctx->vertices[i][1][3] = color->f[3]; 445 } 446 } else { 447 for (i = 0; i < 4; i++) { 448 ctx->vertices[i][1][0] = 0; 449 ctx->vertices[i][1][1] = 0; 450 ctx->vertices[i][1][2] = 0; 451 ctx->vertices[i][1][3] = 0; 452 } 453 } 454} 455 456static void get_texcoords(struct pipe_resource *src, 457 unsigned level, 458 unsigned x1, unsigned y1, 459 unsigned x2, unsigned y2, 460 boolean normalized, float out[4]) 461{ 462 if(normalized) 463 { 464 out[0] = x1 / (float)u_minify(src->width0, level); 465 out[1] = y1 / (float)u_minify(src->height0, level); 466 out[2] = x2 / (float)u_minify(src->width0, level); 467 out[3] = y2 / (float)u_minify(src->height0, level); 468 } 469 else 470 { 471 out[0] = x1; 472 out[1] = y1; 473 out[2] = x2; 474 out[3] = y2; 475 } 476} 477 478static void set_texcoords_in_vertices(const float coord[4], 479 float *out, unsigned stride) 480{ 481 out[0] = coord[0]; /*t0.s*/ 482 out[1] = coord[1]; /*t0.t*/ 483 out += stride; 484 out[0] = coord[2]; /*t1.s*/ 485 out[1] = coord[1]; /*t1.t*/ 486 out += stride; 487 out[0] = coord[2]; /*t2.s*/ 488 out[1] = coord[3]; /*t2.t*/ 489 out += stride; 490 out[0] = coord[0]; /*t3.s*/ 491 out[1] = coord[3]; /*t3.t*/ 492} 493 494static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx, 495 struct pipe_resource *src, 496 unsigned level, 497 unsigned x1, unsigned y1, 498 unsigned x2, unsigned y2) 499{ 500 unsigned i; 501 float coord[4]; 502 503 get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord); 504 set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8); 505 506 for (i = 0; i < 4; i++) { 507 ctx->vertices[i][1][2] = 0; /*r*/ 508 ctx->vertices[i][1][3] = 1; /*q*/ 509 } 510} 511 512static void blitter_set_texcoords_3d(struct blitter_context_priv *ctx, 513 struct pipe_resource *src, 514 unsigned level, 515 unsigned zslice, 516 unsigned x1, unsigned y1, 517 unsigned x2, unsigned y2, 518 boolean normalized) 519{ 520 int i; 521 float r = normalized ? zslice / (float)u_minify(src->depth0, level) : zslice; 522 523 blitter_set_texcoords_2d(ctx, src, level, x1, y1, x2, y2); 524 525 for (i = 0; i < 4; i++) 526 ctx->vertices[i][1][2] = r; /*r*/ 527} 528 529static void blitter_set_texcoords_1d_array(struct blitter_context_priv *ctx, 530 struct pipe_resource *src, 531 unsigned level, 532 unsigned zslice, 533 unsigned x1, unsigned x2) 534{ 535 int i; 536 float r = zslice; 537 538 blitter_set_texcoords_2d(ctx, src, level, x1, 0, x2, 0); 539 540 for (i = 0; i < 4; i++) 541 ctx->vertices[i][1][1] = r; /*r*/ 542} 543 544static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx, 545 struct pipe_resource *src, 546 unsigned level, unsigned face, 547 unsigned x1, unsigned y1, 548 unsigned x2, unsigned y2) 549{ 550 int i; 551 float coord[4]; 552 float st[4][2]; 553 554 get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord); 555 set_texcoords_in_vertices(coord, &st[0][0], 2); 556 557 util_map_texcoords2d_onto_cubemap(face, 558 /* pointer, stride in floats */ 559 &st[0][0], 2, 560 &ctx->vertices[0][1][0], 8); 561 562 for (i = 0; i < 4; i++) 563 ctx->vertices[i][1][3] = 1; /*q*/ 564} 565 566static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx, 567 unsigned width, unsigned height) 568{ 569 ctx->dst_width = width; 570 ctx->dst_height = height; 571} 572 573static INLINE 574void **blitter_get_sampler_state(struct blitter_context_priv *ctx, 575 int miplevel, boolean normalized) 576{ 577 struct pipe_context *pipe = ctx->base.pipe; 578 struct pipe_sampler_state *sampler_state = &ctx->template_sampler_state; 579 580 assert(miplevel < PIPE_MAX_TEXTURE_LEVELS); 581 582 /* Create the sampler state on-demand. */ 583 if (!ctx->sampler_state[miplevel * 2 + normalized]) { 584 sampler_state->lod_bias = miplevel; 585 sampler_state->min_lod = miplevel; 586 sampler_state->max_lod = miplevel; 587 sampler_state->normalized_coords = normalized; 588 589 ctx->sampler_state[miplevel * 2 + normalized] = pipe->create_sampler_state(pipe, 590 sampler_state); 591 } 592 593 /* Return void** so that it can be passed to bind_fragment_sampler_states 594 * directly. */ 595 return &ctx->sampler_state[miplevel * 2 + normalized]; 596} 597 598static INLINE 599void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs) 600{ 601 struct pipe_context *pipe = ctx->base.pipe; 602 603 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); 604 605 if (!ctx->fs_col[num_cbufs]) 606 ctx->fs_col[num_cbufs] = 607 util_make_fragment_cloneinput_shader(pipe, num_cbufs, 608 TGSI_SEMANTIC_GENERIC, 609 TGSI_INTERPOLATE_LINEAR); 610 611 return ctx->fs_col[num_cbufs]; 612} 613 614/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */ 615static unsigned 616pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target) 617{ 618 switch (pipe_tex_target) { 619 case PIPE_TEXTURE_1D: 620 return TGSI_TEXTURE_1D; 621 case PIPE_TEXTURE_2D: 622 return TGSI_TEXTURE_2D; 623 case PIPE_TEXTURE_RECT: 624 return TGSI_TEXTURE_RECT; 625 case PIPE_TEXTURE_3D: 626 return TGSI_TEXTURE_3D; 627 case PIPE_TEXTURE_CUBE: 628 return TGSI_TEXTURE_CUBE; 629 case PIPE_TEXTURE_1D_ARRAY: 630 return TGSI_TEXTURE_1D_ARRAY; 631 case PIPE_TEXTURE_2D_ARRAY: 632 return TGSI_TEXTURE_2D_ARRAY; 633 default: 634 assert(0 && "unexpected texture target"); 635 return TGSI_TEXTURE_UNKNOWN; 636 } 637} 638 639 640static INLINE 641void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, 642 unsigned tex_target) 643{ 644 struct pipe_context *pipe = ctx->base.pipe; 645 646 assert(tex_target < PIPE_MAX_TEXTURE_TYPES); 647 648 /* Create the fragment shader on-demand. */ 649 if (!ctx->fs_texfetch_col[tex_target]) { 650 unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target); 651 652 ctx->fs_texfetch_col[tex_target] = 653 util_make_fragment_tex_shader(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR); 654 } 655 656 return ctx->fs_texfetch_col[tex_target]; 657} 658 659static INLINE 660void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx, 661 unsigned tex_target) 662{ 663 struct pipe_context *pipe = ctx->base.pipe; 664 665 assert(tex_target < PIPE_MAX_TEXTURE_TYPES); 666 667 /* Create the fragment shader on-demand. */ 668 if (!ctx->fs_texfetch_depth[tex_target]) { 669 unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target); 670 671 ctx->fs_texfetch_depth[tex_target] = 672 util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex, 673 TGSI_INTERPOLATE_LINEAR); 674 } 675 676 return ctx->fs_texfetch_depth[tex_target]; 677} 678 679static void blitter_draw_rectangle(struct blitter_context *blitter, 680 unsigned x1, unsigned y1, 681 unsigned x2, unsigned y2, 682 float depth, 683 enum blitter_attrib_type type, 684 const union pipe_color_union *attrib) 685{ 686 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 687 688 switch (type) { 689 case UTIL_BLITTER_ATTRIB_COLOR: 690 blitter_set_clear_color(ctx, attrib); 691 break; 692 693 case UTIL_BLITTER_ATTRIB_TEXCOORD: 694 set_texcoords_in_vertices(attrib->f, &ctx->vertices[0][1][0], 8); 695 break; 696 697 default:; 698 } 699 700 blitter_set_rectangle(ctx, x1, y1, x2, y2, depth); 701 ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf, 702 0, ctx->vbuf->width0); 703 util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0, 704 PIPE_PRIM_TRIANGLE_FAN, 4, 2); 705} 706 707static void util_blitter_clear_custom(struct blitter_context *blitter, 708 unsigned width, unsigned height, 709 unsigned num_cbufs, 710 unsigned clear_buffers, 711 const union pipe_color_union *color, 712 double depth, unsigned stencil, 713 void *custom_blend, void *custom_dsa) 714{ 715 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 716 struct pipe_context *pipe = ctx->base.pipe; 717 struct pipe_stencil_ref sr = { { 0 } }; 718 719 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); 720 721 blitter_set_running_flag(ctx); 722 blitter_check_saved_vertex_states(ctx); 723 blitter_check_saved_fragment_states(ctx); 724 725 /* bind states */ 726 if (custom_blend) { 727 pipe->bind_blend_state(pipe, custom_blend); 728 } else if (clear_buffers & PIPE_CLEAR_COLOR) { 729 pipe->bind_blend_state(pipe, ctx->blend_write_color); 730 } else { 731 pipe->bind_blend_state(pipe, ctx->blend_keep_color); 732 } 733 734 if (custom_dsa) { 735 pipe->bind_depth_stencil_alpha_state(pipe, custom_dsa); 736 } else if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { 737 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); 738 } else if (clear_buffers & PIPE_CLEAR_DEPTH) { 739 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); 740 } else if (clear_buffers & PIPE_CLEAR_STENCIL) { 741 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); 742 } else { 743 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 744 } 745 746 sr.ref_value[0] = stencil & 0xff; 747 pipe->set_stencil_ref(pipe, &sr); 748 749 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 750 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 751 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs)); 752 pipe->bind_vs_state(pipe, ctx->vs); 753 754 blitter_set_dst_dimensions(ctx, width, height); 755 blitter->draw_rectangle(blitter, 0, 0, width, height, depth, 756 UTIL_BLITTER_ATTRIB_COLOR, color); 757 758 blitter_restore_vertex_states(ctx); 759 blitter_restore_fragment_states(ctx); 760 blitter_unset_running_flag(ctx); 761} 762 763void util_blitter_clear(struct blitter_context *blitter, 764 unsigned width, unsigned height, 765 unsigned num_cbufs, 766 unsigned clear_buffers, 767 const union pipe_color_union *color, 768 double depth, unsigned stencil) 769{ 770 util_blitter_clear_custom(blitter, width, height, num_cbufs, 771 clear_buffers, color, depth, stencil, 772 NULL, NULL); 773} 774 775void util_blitter_clear_depth_custom(struct blitter_context *blitter, 776 unsigned width, unsigned height, 777 double depth, void *custom_dsa) 778{ 779 static const union pipe_color_union color; 780 util_blitter_clear_custom(blitter, width, height, 0, 781 0, &color, depth, 0, NULL, custom_dsa); 782} 783 784static 785boolean is_overlap(unsigned sx1, unsigned sx2, unsigned sy1, unsigned sy2, 786 unsigned dx1, unsigned dx2, unsigned dy1, unsigned dy2) 787{ 788 return sx1 < dx2 && sx2 > dx1 && sy1 < dy2 && sy2 > dy1; 789} 790 791void util_blitter_copy_texture(struct blitter_context *blitter, 792 struct pipe_resource *dst, 793 unsigned dstlevel, 794 unsigned dstx, unsigned dsty, unsigned dstz, 795 struct pipe_resource *src, 796 unsigned srclevel, 797 const struct pipe_box *srcbox, 798 boolean ignore_stencil) 799{ 800 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 801 struct pipe_context *pipe = ctx->base.pipe; 802 struct pipe_screen *screen = pipe->screen; 803 struct pipe_surface *dstsurf, surf_templ; 804 struct pipe_framebuffer_state fb_state; 805 struct pipe_sampler_view viewTempl, *view; 806 unsigned bind; 807 unsigned width = srcbox->width; 808 unsigned height = srcbox->height; 809 boolean is_stencil, is_depth; 810 boolean normalized; 811 812 /* Give up if textures are not set. */ 813 assert(dst && src); 814 if (!dst || !src) 815 return; 816 817 /* Sanity checks. */ 818 if (dst == src) { 819 assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height, 820 dstx, dstx + width, dsty, dsty + height)); 821 } 822 assert(src->target < PIPE_MAX_TEXTURE_TYPES); 823 /* XXX should handle 3d regions */ 824 assert(srcbox->depth == 1); 825 826 /* Is this a ZS format? */ 827 is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0; 828 is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0; 829 830 if (is_depth || is_stencil) 831 bind = PIPE_BIND_DEPTH_STENCIL; 832 else 833 bind = PIPE_BIND_RENDER_TARGET; 834 835 /* Check if we can sample from and render to the surfaces. */ 836 /* (assuming copying a stencil buffer is not possible) */ 837 if ((!ignore_stencil && is_stencil) || 838 !screen->is_format_supported(screen, dst->format, dst->target, 839 dst->nr_samples, bind) || 840 !screen->is_format_supported(screen, src->format, src->target, 841 src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) { 842 ctx->base.running = TRUE; 843 util_resource_copy_region(pipe, dst, dstlevel, dstx, dsty, dstz, 844 src, srclevel, srcbox); 845 ctx->base.running = FALSE; 846 return; 847 } 848 849 /* Get surface. */ 850 memset(&surf_templ, 0, sizeof(surf_templ)); 851 u_surface_default_template(&surf_templ, dst, bind); 852 surf_templ.format = util_format_linear(dst->format); 853 surf_templ.u.tex.level = dstlevel; 854 surf_templ.u.tex.first_layer = dstz; 855 surf_templ.u.tex.last_layer = dstz; 856 dstsurf = pipe->create_surface(pipe, dst, &surf_templ); 857 858 /* Check whether the states are properly saved. */ 859 blitter_set_running_flag(ctx); 860 blitter_check_saved_vertex_states(ctx); 861 blitter_check_saved_fragment_states(ctx); 862 blitter_check_saved_textures(ctx); 863 blitter_check_saved_fb_state(ctx); 864 865 /* Initialize framebuffer state. */ 866 fb_state.width = dstsurf->width; 867 fb_state.height = dstsurf->height; 868 869 if (is_depth) { 870 pipe->bind_blend_state(pipe, ctx->blend_keep_color); 871 pipe->bind_depth_stencil_alpha_state(pipe, 872 ctx->dsa_write_depth_keep_stencil); 873 pipe->bind_fs_state(pipe, 874 blitter_get_fs_texfetch_depth(ctx, src->target)); 875 876 fb_state.nr_cbufs = 0; 877 fb_state.zsbuf = dstsurf; 878 } else { 879 pipe->bind_blend_state(pipe, ctx->blend_write_color); 880 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 881 pipe->bind_fs_state(pipe, 882 blitter_get_fs_texfetch_col(ctx, src->target)); 883 884 fb_state.nr_cbufs = 1; 885 fb_state.cbufs[0] = dstsurf; 886 fb_state.zsbuf = 0; 887 } 888 889 normalized = src->target != PIPE_TEXTURE_RECT; 890 891 /* Initialize sampler view. */ 892 u_sampler_view_default_template(&viewTempl, src, util_format_linear(src->format)); 893 view = pipe->create_sampler_view(pipe, src, &viewTempl); 894 895 /* Set rasterizer state, shaders, and textures. */ 896 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 897 pipe->bind_vs_state(pipe, ctx->vs); 898 pipe->bind_fragment_sampler_states(pipe, 1, 899 blitter_get_sampler_state(ctx, srclevel, normalized)); 900 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 901 pipe->set_fragment_sampler_views(pipe, 1, &view); 902 pipe->set_framebuffer_state(pipe, &fb_state); 903 904 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); 905 906 switch (src->target) { 907 /* Draw the quad with the draw_rectangle callback. */ 908 case PIPE_TEXTURE_1D: 909 case PIPE_TEXTURE_2D: 910 case PIPE_TEXTURE_RECT: 911 { 912 /* Set texture coordinates. - use a pipe color union 913 * for interface purposes 914 */ 915 union pipe_color_union coord; 916 get_texcoords(src, srclevel, srcbox->x, srcbox->y, 917 srcbox->x+width, srcbox->y+height, normalized, coord.f); 918 919 /* Draw. */ 920 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, 921 UTIL_BLITTER_ATTRIB_TEXCOORD, &coord); 922 } 923 break; 924 925 /* Draw the quad with the generic codepath. */ 926 default: 927 /* Set texture coordinates. */ 928 switch (src->target) { 929 case PIPE_TEXTURE_1D_ARRAY: 930 blitter_set_texcoords_1d_array(ctx, src, srclevel, srcbox->y, 931 srcbox->x, srcbox->x + width); 932 break; 933 934 case PIPE_TEXTURE_2D_ARRAY: 935 case PIPE_TEXTURE_3D: 936 blitter_set_texcoords_3d(ctx, src, srclevel, srcbox->z, 937 srcbox->x, srcbox->y, 938 srcbox->x + width, srcbox->y + height, 939 src->target == PIPE_TEXTURE_3D); 940 break; 941 942 case PIPE_TEXTURE_CUBE: 943 blitter_set_texcoords_cube(ctx, src, srclevel, srcbox->z, 944 srcbox->x, srcbox->y, 945 srcbox->x + width, srcbox->y + height); 946 break; 947 948 default: 949 assert(0); 950 } 951 952 /* Draw. */ 953 blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0); 954 ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf, 955 0, ctx->vbuf->width0); 956 util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0, 957 PIPE_PRIM_TRIANGLE_FAN, 4, 2); 958 break; 959 } 960 961 blitter_restore_vertex_states(ctx); 962 blitter_restore_fragment_states(ctx); 963 blitter_restore_textures(ctx); 964 blitter_restore_fb_state(ctx); 965 blitter_unset_running_flag(ctx); 966 967 pipe_surface_reference(&dstsurf, NULL); 968 pipe_sampler_view_reference(&view, NULL); 969} 970 971/* Clear a region of a color surface to a constant value. */ 972void util_blitter_clear_render_target(struct blitter_context *blitter, 973 struct pipe_surface *dstsurf, 974 const union pipe_color_union *color, 975 unsigned dstx, unsigned dsty, 976 unsigned width, unsigned height) 977{ 978 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 979 struct pipe_context *pipe = ctx->base.pipe; 980 struct pipe_framebuffer_state fb_state; 981 982 assert(dstsurf->texture); 983 if (!dstsurf->texture) 984 return; 985 986 /* check the saved state */ 987 blitter_set_running_flag(ctx); 988 blitter_check_saved_vertex_states(ctx); 989 blitter_check_saved_fragment_states(ctx); 990 blitter_check_saved_fb_state(ctx); 991 992 /* bind states */ 993 pipe->bind_blend_state(pipe, ctx->blend_write_color); 994 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 995 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 996 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1)); 997 pipe->bind_vs_state(pipe, ctx->vs); 998 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 999 1000 /* set a framebuffer state */ 1001 fb_state.width = dstsurf->width; 1002 fb_state.height = dstsurf->height; 1003 fb_state.nr_cbufs = 1; 1004 fb_state.cbufs[0] = dstsurf; 1005 fb_state.zsbuf = 0; 1006 pipe->set_framebuffer_state(pipe, &fb_state); 1007 1008 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); 1009 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, 1010 UTIL_BLITTER_ATTRIB_COLOR, color); 1011 1012 blitter_restore_vertex_states(ctx); 1013 blitter_restore_fragment_states(ctx); 1014 blitter_restore_fb_state(ctx); 1015 blitter_unset_running_flag(ctx); 1016} 1017 1018/* Clear a region of a depth stencil surface. */ 1019void util_blitter_clear_depth_stencil(struct blitter_context *blitter, 1020 struct pipe_surface *dstsurf, 1021 unsigned clear_flags, 1022 double depth, 1023 unsigned stencil, 1024 unsigned dstx, unsigned dsty, 1025 unsigned width, unsigned height) 1026{ 1027 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 1028 struct pipe_context *pipe = ctx->base.pipe; 1029 struct pipe_framebuffer_state fb_state; 1030 struct pipe_stencil_ref sr = { { 0 } }; 1031 1032 assert(dstsurf->texture); 1033 if (!dstsurf->texture) 1034 return; 1035 1036 /* check the saved state */ 1037 blitter_set_running_flag(ctx); 1038 blitter_check_saved_vertex_states(ctx); 1039 blitter_check_saved_fragment_states(ctx); 1040 blitter_check_saved_fb_state(ctx); 1041 1042 /* bind states */ 1043 pipe->bind_blend_state(pipe, ctx->blend_keep_color); 1044 if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { 1045 sr.ref_value[0] = stencil & 0xff; 1046 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); 1047 pipe->set_stencil_ref(pipe, &sr); 1048 } 1049 else if (clear_flags & PIPE_CLEAR_DEPTH) { 1050 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); 1051 } 1052 else if (clear_flags & PIPE_CLEAR_STENCIL) { 1053 sr.ref_value[0] = stencil & 0xff; 1054 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); 1055 pipe->set_stencil_ref(pipe, &sr); 1056 } 1057 else 1058 /* hmm that should be illegal probably, or make it a no-op somewhere */ 1059 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 1060 1061 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 1062 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0)); 1063 pipe->bind_vs_state(pipe, ctx->vs); 1064 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 1065 1066 /* set a framebuffer state */ 1067 fb_state.width = dstsurf->width; 1068 fb_state.height = dstsurf->height; 1069 fb_state.nr_cbufs = 0; 1070 fb_state.cbufs[0] = 0; 1071 fb_state.zsbuf = dstsurf; 1072 pipe->set_framebuffer_state(pipe, &fb_state); 1073 1074 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); 1075 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, depth, 1076 UTIL_BLITTER_ATTRIB_NONE, NULL); 1077 1078 blitter_restore_vertex_states(ctx); 1079 blitter_restore_fragment_states(ctx); 1080 blitter_restore_fb_state(ctx); 1081 blitter_unset_running_flag(ctx); 1082} 1083 1084/* draw a rectangle across a region using a custom dsa stage - for r600g */ 1085void util_blitter_custom_depth_stencil(struct blitter_context *blitter, 1086 struct pipe_surface *zsurf, 1087 struct pipe_surface *cbsurf, 1088 void *dsa_stage, float depth) 1089{ 1090 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 1091 struct pipe_context *pipe = ctx->base.pipe; 1092 struct pipe_framebuffer_state fb_state; 1093 1094 assert(zsurf->texture); 1095 if (!zsurf->texture) 1096 return; 1097 1098 /* check the saved state */ 1099 blitter_set_running_flag(ctx); 1100 blitter_check_saved_vertex_states(ctx); 1101 blitter_check_saved_fragment_states(ctx); 1102 blitter_check_saved_fb_state(ctx); 1103 1104 /* bind states */ 1105 pipe->bind_blend_state(pipe, ctx->blend_write_color); 1106 pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage); 1107 1108 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 1109 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0)); 1110 pipe->bind_vs_state(pipe, ctx->vs); 1111 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 1112 1113 /* set a framebuffer state */ 1114 fb_state.width = zsurf->width; 1115 fb_state.height = zsurf->height; 1116 fb_state.nr_cbufs = 1; 1117 if (cbsurf) { 1118 fb_state.cbufs[0] = cbsurf; 1119 fb_state.nr_cbufs = 1; 1120 } else { 1121 fb_state.cbufs[0] = NULL; 1122 fb_state.nr_cbufs = 0; 1123 } 1124 fb_state.zsbuf = zsurf; 1125 pipe->set_framebuffer_state(pipe, &fb_state); 1126 1127 blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height); 1128 blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth, 1129 UTIL_BLITTER_ATTRIB_NONE, NULL); 1130 1131 blitter_restore_vertex_states(ctx); 1132 blitter_restore_fragment_states(ctx); 1133 blitter_restore_fb_state(ctx); 1134 blitter_unset_running_flag(ctx); 1135} 1136