u_blitter.c revision 6dd284f7c8fac22f64c13fdf9909094f5ec59086
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_check_saved_CSOs(struct blitter_context_priv *ctx) 267{ 268 if (ctx->base.running) { 269 _debug_printf("u_blitter: Caught recursion on save. " 270 "This is a driver bug.\n"); 271 } 272 ctx->base.running = TRUE; 273 274 /* make sure these CSOs have been saved */ 275 assert(ctx->base.saved_blend_state != INVALID_PTR && 276 ctx->base.saved_dsa_state != INVALID_PTR && 277 ctx->base.saved_rs_state != INVALID_PTR && 278 ctx->base.saved_fs != INVALID_PTR && 279 ctx->base.saved_vs != INVALID_PTR && 280 ctx->base.saved_velem_state != INVALID_PTR); 281} 282 283static void blitter_restore_CSOs(struct blitter_context_priv *ctx) 284{ 285 struct pipe_context *pipe = ctx->base.pipe; 286 unsigned i; 287 288 /* restore the state objects which are always required to be saved */ 289 pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state); 290 pipe->bind_vs_state(pipe, ctx->base.saved_vs); 291 pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state); 292 293 ctx->base.saved_rs_state = INVALID_PTR; 294 ctx->base.saved_vs = INVALID_PTR; 295 ctx->base.saved_velem_state = INVALID_PTR; 296 297 /* restore the state objects which are required to be saved for clear/copy 298 */ 299 if (ctx->base.saved_blend_state != INVALID_PTR) { 300 pipe->bind_blend_state(pipe, ctx->base.saved_blend_state); 301 ctx->base.saved_blend_state = INVALID_PTR; 302 } 303 if (ctx->base.saved_dsa_state != INVALID_PTR) { 304 pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state); 305 ctx->base.saved_dsa_state = INVALID_PTR; 306 } 307 if (ctx->base.saved_fs != INVALID_PTR) { 308 pipe->bind_fs_state(pipe, ctx->base.saved_fs); 309 ctx->base.saved_fs = INVALID_PTR; 310 } 311 312 pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref); 313 pipe->set_viewport_state(pipe, &ctx->base.saved_viewport); 314 pipe->set_clip_state(pipe, &ctx->base.saved_clip); 315 316 if (ctx->base.saved_fb_state.nr_cbufs != ~0) { 317 pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state); 318 util_unreference_framebuffer_state(&ctx->base.saved_fb_state); 319 ctx->base.saved_fb_state.nr_cbufs = ~0; 320 } 321 322 if (ctx->base.saved_num_sampler_states != ~0) { 323 pipe->bind_fragment_sampler_states(pipe, 324 ctx->base.saved_num_sampler_states, 325 ctx->base.saved_sampler_states); 326 ctx->base.saved_num_sampler_states = ~0; 327 } 328 329 if (ctx->base.saved_num_sampler_views != ~0) { 330 pipe->set_fragment_sampler_views(pipe, 331 ctx->base.saved_num_sampler_views, 332 ctx->base.saved_sampler_views); 333 334 for (i = 0; i < ctx->base.saved_num_sampler_views; i++) 335 pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i], 336 NULL); 337 338 ctx->base.saved_num_sampler_views = ~0; 339 } 340 341 if (ctx->base.saved_num_vertex_buffers != ~0) { 342 pipe->set_vertex_buffers(pipe, 343 ctx->base.saved_num_vertex_buffers, 344 ctx->base.saved_vertex_buffers); 345 346 for (i = 0; i < ctx->base.saved_num_vertex_buffers; i++) { 347 if (ctx->base.saved_vertex_buffers[i].buffer) { 348 pipe_resource_reference(&ctx->base.saved_vertex_buffers[i].buffer, 349 NULL); 350 } 351 } 352 ctx->base.saved_num_vertex_buffers = ~0; 353 } 354 355 if (!ctx->base.running) { 356 _debug_printf("u_blitter: Caught recursion on restore. " 357 "This is a driver bug.\n"); 358 } 359 ctx->base.running = FALSE; 360} 361 362static void blitter_set_rectangle(struct blitter_context_priv *ctx, 363 unsigned x1, unsigned y1, 364 unsigned x2, unsigned y2, 365 float depth) 366{ 367 int i; 368 369 /* set vertex positions */ 370 ctx->vertices[0][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v0.x*/ 371 ctx->vertices[0][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v0.y*/ 372 373 ctx->vertices[1][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v1.x*/ 374 ctx->vertices[1][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v1.y*/ 375 376 ctx->vertices[2][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v2.x*/ 377 ctx->vertices[2][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v2.y*/ 378 379 ctx->vertices[3][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v3.x*/ 380 ctx->vertices[3][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v3.y*/ 381 382 for (i = 0; i < 4; i++) 383 ctx->vertices[i][0][2] = depth; /*z*/ 384 385 /* viewport */ 386 ctx->viewport.scale[0] = 0.5f * ctx->dst_width; 387 ctx->viewport.scale[1] = 0.5f * ctx->dst_height; 388 ctx->viewport.scale[2] = 1.0f; 389 ctx->viewport.scale[3] = 1.0f; 390 ctx->viewport.translate[0] = 0.5f * ctx->dst_width; 391 ctx->viewport.translate[1] = 0.5f * ctx->dst_height; 392 ctx->viewport.translate[2] = 0.0f; 393 ctx->viewport.translate[3] = 0.0f; 394 ctx->base.pipe->set_viewport_state(ctx->base.pipe, &ctx->viewport); 395 396 /* clip */ 397 ctx->base.pipe->set_clip_state(ctx->base.pipe, &ctx->clip); 398} 399 400static void blitter_set_clear_color(struct blitter_context_priv *ctx, 401 const union pipe_color_union *color) 402{ 403 int i; 404 405 if (color) { 406 for (i = 0; i < 4; i++) { 407 ctx->vertices[i][1][0] = color->f[0]; 408 ctx->vertices[i][1][1] = color->f[1]; 409 ctx->vertices[i][1][2] = color->f[2]; 410 ctx->vertices[i][1][3] = color->f[3]; 411 } 412 } else { 413 for (i = 0; i < 4; i++) { 414 ctx->vertices[i][1][0] = 0; 415 ctx->vertices[i][1][1] = 0; 416 ctx->vertices[i][1][2] = 0; 417 ctx->vertices[i][1][3] = 0; 418 } 419 } 420} 421 422static void get_texcoords(struct pipe_resource *src, 423 unsigned level, 424 unsigned x1, unsigned y1, 425 unsigned x2, unsigned y2, 426 boolean normalized, float out[4]) 427{ 428 if(normalized) 429 { 430 out[0] = x1 / (float)u_minify(src->width0, level); 431 out[1] = y1 / (float)u_minify(src->height0, level); 432 out[2] = x2 / (float)u_minify(src->width0, level); 433 out[3] = y2 / (float)u_minify(src->height0, level); 434 } 435 else 436 { 437 out[0] = x1; 438 out[1] = y1; 439 out[2] = x2; 440 out[3] = y2; 441 } 442} 443 444static void set_texcoords_in_vertices(const float coord[4], 445 float *out, unsigned stride) 446{ 447 out[0] = coord[0]; /*t0.s*/ 448 out[1] = coord[1]; /*t0.t*/ 449 out += stride; 450 out[0] = coord[2]; /*t1.s*/ 451 out[1] = coord[1]; /*t1.t*/ 452 out += stride; 453 out[0] = coord[2]; /*t2.s*/ 454 out[1] = coord[3]; /*t2.t*/ 455 out += stride; 456 out[0] = coord[0]; /*t3.s*/ 457 out[1] = coord[3]; /*t3.t*/ 458} 459 460static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx, 461 struct pipe_resource *src, 462 unsigned level, 463 unsigned x1, unsigned y1, 464 unsigned x2, unsigned y2) 465{ 466 unsigned i; 467 float coord[4]; 468 469 get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord); 470 set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8); 471 472 for (i = 0; i < 4; i++) { 473 ctx->vertices[i][1][2] = 0; /*r*/ 474 ctx->vertices[i][1][3] = 1; /*q*/ 475 } 476} 477 478static void blitter_set_texcoords_3d(struct blitter_context_priv *ctx, 479 struct pipe_resource *src, 480 unsigned level, 481 unsigned zslice, 482 unsigned x1, unsigned y1, 483 unsigned x2, unsigned y2, 484 boolean normalized) 485{ 486 int i; 487 float r = normalized ? zslice / (float)u_minify(src->depth0, level) : zslice; 488 489 blitter_set_texcoords_2d(ctx, src, level, x1, y1, x2, y2); 490 491 for (i = 0; i < 4; i++) 492 ctx->vertices[i][1][2] = r; /*r*/ 493} 494 495static void blitter_set_texcoords_1d_array(struct blitter_context_priv *ctx, 496 struct pipe_resource *src, 497 unsigned level, 498 unsigned zslice, 499 unsigned x1, unsigned x2) 500{ 501 int i; 502 float r = zslice; 503 504 blitter_set_texcoords_2d(ctx, src, level, x1, 0, x2, 0); 505 506 for (i = 0; i < 4; i++) 507 ctx->vertices[i][1][1] = r; /*r*/ 508} 509 510static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx, 511 struct pipe_resource *src, 512 unsigned level, unsigned face, 513 unsigned x1, unsigned y1, 514 unsigned x2, unsigned y2) 515{ 516 int i; 517 float coord[4]; 518 float st[4][2]; 519 520 get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord); 521 set_texcoords_in_vertices(coord, &st[0][0], 2); 522 523 util_map_texcoords2d_onto_cubemap(face, 524 /* pointer, stride in floats */ 525 &st[0][0], 2, 526 &ctx->vertices[0][1][0], 8); 527 528 for (i = 0; i < 4; i++) 529 ctx->vertices[i][1][3] = 1; /*q*/ 530} 531 532static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx, 533 unsigned width, unsigned height) 534{ 535 ctx->dst_width = width; 536 ctx->dst_height = height; 537} 538 539static INLINE 540void **blitter_get_sampler_state(struct blitter_context_priv *ctx, 541 int miplevel, boolean normalized) 542{ 543 struct pipe_context *pipe = ctx->base.pipe; 544 struct pipe_sampler_state *sampler_state = &ctx->template_sampler_state; 545 546 assert(miplevel < PIPE_MAX_TEXTURE_LEVELS); 547 548 /* Create the sampler state on-demand. */ 549 if (!ctx->sampler_state[miplevel * 2 + normalized]) { 550 sampler_state->lod_bias = miplevel; 551 sampler_state->min_lod = miplevel; 552 sampler_state->max_lod = miplevel; 553 sampler_state->normalized_coords = normalized; 554 555 ctx->sampler_state[miplevel * 2 + normalized] = pipe->create_sampler_state(pipe, 556 sampler_state); 557 } 558 559 /* Return void** so that it can be passed to bind_fragment_sampler_states 560 * directly. */ 561 return &ctx->sampler_state[miplevel * 2 + normalized]; 562} 563 564static INLINE 565void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs) 566{ 567 struct pipe_context *pipe = ctx->base.pipe; 568 569 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); 570 571 if (!ctx->fs_col[num_cbufs]) 572 ctx->fs_col[num_cbufs] = 573 util_make_fragment_cloneinput_shader(pipe, num_cbufs, 574 TGSI_SEMANTIC_GENERIC, 575 TGSI_INTERPOLATE_LINEAR); 576 577 return ctx->fs_col[num_cbufs]; 578} 579 580/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */ 581static unsigned 582pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target) 583{ 584 switch (pipe_tex_target) { 585 case PIPE_TEXTURE_1D: 586 return TGSI_TEXTURE_1D; 587 case PIPE_TEXTURE_2D: 588 return TGSI_TEXTURE_2D; 589 case PIPE_TEXTURE_RECT: 590 return TGSI_TEXTURE_RECT; 591 case PIPE_TEXTURE_3D: 592 return TGSI_TEXTURE_3D; 593 case PIPE_TEXTURE_CUBE: 594 return TGSI_TEXTURE_CUBE; 595 case PIPE_TEXTURE_1D_ARRAY: 596 return TGSI_TEXTURE_1D_ARRAY; 597 case PIPE_TEXTURE_2D_ARRAY: 598 return TGSI_TEXTURE_2D_ARRAY; 599 default: 600 assert(0 && "unexpected texture target"); 601 return TGSI_TEXTURE_UNKNOWN; 602 } 603} 604 605 606static INLINE 607void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, 608 unsigned tex_target) 609{ 610 struct pipe_context *pipe = ctx->base.pipe; 611 612 assert(tex_target < PIPE_MAX_TEXTURE_TYPES); 613 614 /* Create the fragment shader on-demand. */ 615 if (!ctx->fs_texfetch_col[tex_target]) { 616 unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target); 617 618 ctx->fs_texfetch_col[tex_target] = 619 util_make_fragment_tex_shader(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR); 620 } 621 622 return ctx->fs_texfetch_col[tex_target]; 623} 624 625static INLINE 626void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx, 627 unsigned tex_target) 628{ 629 struct pipe_context *pipe = ctx->base.pipe; 630 631 assert(tex_target < PIPE_MAX_TEXTURE_TYPES); 632 633 /* Create the fragment shader on-demand. */ 634 if (!ctx->fs_texfetch_depth[tex_target]) { 635 unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target); 636 637 ctx->fs_texfetch_depth[tex_target] = 638 util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex, 639 TGSI_INTERPOLATE_LINEAR); 640 } 641 642 return ctx->fs_texfetch_depth[tex_target]; 643} 644 645static void blitter_draw_rectangle(struct blitter_context *blitter, 646 unsigned x1, unsigned y1, 647 unsigned x2, unsigned y2, 648 float depth, 649 enum blitter_attrib_type type, 650 const union pipe_color_union *attrib) 651{ 652 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 653 654 switch (type) { 655 case UTIL_BLITTER_ATTRIB_COLOR: 656 blitter_set_clear_color(ctx, attrib); 657 break; 658 659 case UTIL_BLITTER_ATTRIB_TEXCOORD: 660 set_texcoords_in_vertices(attrib->f, &ctx->vertices[0][1][0], 8); 661 break; 662 663 default:; 664 } 665 666 blitter_set_rectangle(ctx, x1, y1, x2, y2, depth); 667 ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf, 668 0, ctx->vbuf->width0); 669 util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0, 670 PIPE_PRIM_TRIANGLE_FAN, 4, 2); 671} 672 673static void util_blitter_clear_custom(struct blitter_context *blitter, 674 unsigned width, unsigned height, 675 unsigned num_cbufs, 676 unsigned clear_buffers, 677 const union pipe_color_union *color, 678 double depth, unsigned stencil, 679 void *custom_blend, void *custom_dsa) 680{ 681 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 682 struct pipe_context *pipe = ctx->base.pipe; 683 struct pipe_stencil_ref sr = { { 0 } }; 684 685 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); 686 687 blitter_check_saved_CSOs(ctx); 688 689 /* bind CSOs */ 690 if (custom_blend) { 691 pipe->bind_blend_state(pipe, custom_blend); 692 } else if (clear_buffers & PIPE_CLEAR_COLOR) { 693 pipe->bind_blend_state(pipe, ctx->blend_write_color); 694 } else { 695 pipe->bind_blend_state(pipe, ctx->blend_keep_color); 696 } 697 698 if (custom_dsa) { 699 pipe->bind_depth_stencil_alpha_state(pipe, custom_dsa); 700 } else if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { 701 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); 702 } else if (clear_buffers & PIPE_CLEAR_DEPTH) { 703 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); 704 } else if (clear_buffers & PIPE_CLEAR_STENCIL) { 705 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); 706 } else { 707 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 708 } 709 710 sr.ref_value[0] = stencil & 0xff; 711 pipe->set_stencil_ref(pipe, &sr); 712 713 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 714 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 715 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs)); 716 pipe->bind_vs_state(pipe, ctx->vs); 717 718 blitter_set_dst_dimensions(ctx, width, height); 719 blitter->draw_rectangle(blitter, 0, 0, width, height, depth, 720 UTIL_BLITTER_ATTRIB_COLOR, color); 721 blitter_restore_CSOs(ctx); 722} 723 724void util_blitter_clear(struct blitter_context *blitter, 725 unsigned width, unsigned height, 726 unsigned num_cbufs, 727 unsigned clear_buffers, 728 const union pipe_color_union *color, 729 double depth, unsigned stencil) 730{ 731 util_blitter_clear_custom(blitter, width, height, num_cbufs, 732 clear_buffers, color, depth, stencil, 733 NULL, NULL); 734} 735 736void util_blitter_clear_depth_custom(struct blitter_context *blitter, 737 unsigned width, unsigned height, 738 double depth, void *custom_dsa) 739{ 740 static const union pipe_color_union color; 741 util_blitter_clear_custom(blitter, width, height, 0, 742 0, &color, depth, 0, NULL, custom_dsa); 743} 744 745static 746boolean is_overlap(unsigned sx1, unsigned sx2, unsigned sy1, unsigned sy2, 747 unsigned dx1, unsigned dx2, unsigned dy1, unsigned dy2) 748{ 749 return sx1 < dx2 && sx2 > dx1 && sy1 < dy2 && sy2 > dy1; 750} 751 752void util_blitter_copy_texture(struct blitter_context *blitter, 753 struct pipe_resource *dst, 754 unsigned dstlevel, 755 unsigned dstx, unsigned dsty, unsigned dstz, 756 struct pipe_resource *src, 757 unsigned srclevel, 758 const struct pipe_box *srcbox, 759 boolean ignore_stencil) 760{ 761 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 762 struct pipe_context *pipe = ctx->base.pipe; 763 struct pipe_screen *screen = pipe->screen; 764 struct pipe_surface *dstsurf, surf_templ; 765 struct pipe_framebuffer_state fb_state; 766 struct pipe_sampler_view viewTempl, *view; 767 unsigned bind; 768 unsigned width = srcbox->width; 769 unsigned height = srcbox->height; 770 boolean is_stencil, is_depth; 771 boolean normalized; 772 773 /* Give up if textures are not set. */ 774 assert(dst && src); 775 if (!dst || !src) 776 return; 777 778 /* Sanity checks. */ 779 if (dst == src) { 780 assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height, 781 dstx, dstx + width, dsty, dsty + height)); 782 } 783 assert(src->target < PIPE_MAX_TEXTURE_TYPES); 784 /* XXX should handle 3d regions */ 785 assert(srcbox->depth == 1); 786 787 /* Is this a ZS format? */ 788 is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0; 789 is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0; 790 791 if (is_depth || is_stencil) 792 bind = PIPE_BIND_DEPTH_STENCIL; 793 else 794 bind = PIPE_BIND_RENDER_TARGET; 795 796 /* Check if we can sample from and render to the surfaces. */ 797 /* (assuming copying a stencil buffer is not possible) */ 798 if ((!ignore_stencil && is_stencil) || 799 !screen->is_format_supported(screen, dst->format, dst->target, 800 dst->nr_samples, bind) || 801 !screen->is_format_supported(screen, src->format, src->target, 802 src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) { 803 ctx->base.running = TRUE; 804 util_resource_copy_region(pipe, dst, dstlevel, dstx, dsty, dstz, 805 src, srclevel, srcbox); 806 ctx->base.running = FALSE; 807 return; 808 } 809 810 /* Get surface. */ 811 memset(&surf_templ, 0, sizeof(surf_templ)); 812 u_surface_default_template(&surf_templ, dst, bind); 813 surf_templ.format = util_format_linear(dst->format); 814 surf_templ.u.tex.level = dstlevel; 815 surf_templ.u.tex.first_layer = dstz; 816 surf_templ.u.tex.last_layer = dstz; 817 dstsurf = pipe->create_surface(pipe, dst, &surf_templ); 818 819 /* Check whether the states are properly saved. */ 820 blitter_check_saved_CSOs(ctx); 821 assert(blitter->saved_fb_state.nr_cbufs != ~0); 822 assert(blitter->saved_num_sampler_views != ~0); 823 assert(blitter->saved_num_sampler_states != ~0); 824 825 /* Initialize framebuffer state. */ 826 fb_state.width = dstsurf->width; 827 fb_state.height = dstsurf->height; 828 829 if (is_depth) { 830 pipe->bind_blend_state(pipe, ctx->blend_keep_color); 831 pipe->bind_depth_stencil_alpha_state(pipe, 832 ctx->dsa_write_depth_keep_stencil); 833 pipe->bind_fs_state(pipe, 834 blitter_get_fs_texfetch_depth(ctx, src->target)); 835 836 fb_state.nr_cbufs = 0; 837 fb_state.zsbuf = dstsurf; 838 } else { 839 pipe->bind_blend_state(pipe, ctx->blend_write_color); 840 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 841 pipe->bind_fs_state(pipe, 842 blitter_get_fs_texfetch_col(ctx, src->target)); 843 844 fb_state.nr_cbufs = 1; 845 fb_state.cbufs[0] = dstsurf; 846 fb_state.zsbuf = 0; 847 } 848 849 normalized = src->target != PIPE_TEXTURE_RECT; 850 851 /* Initialize sampler view. */ 852 u_sampler_view_default_template(&viewTempl, src, util_format_linear(src->format)); 853 view = pipe->create_sampler_view(pipe, src, &viewTempl); 854 855 /* Set rasterizer state, shaders, and textures. */ 856 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 857 pipe->bind_vs_state(pipe, ctx->vs); 858 pipe->bind_fragment_sampler_states(pipe, 1, 859 blitter_get_sampler_state(ctx, srclevel, normalized)); 860 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 861 pipe->set_fragment_sampler_views(pipe, 1, &view); 862 pipe->set_framebuffer_state(pipe, &fb_state); 863 864 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); 865 866 switch (src->target) { 867 /* Draw the quad with the draw_rectangle callback. */ 868 case PIPE_TEXTURE_1D: 869 case PIPE_TEXTURE_2D: 870 case PIPE_TEXTURE_RECT: 871 { 872 /* Set texture coordinates. - use a pipe color union 873 * for interface purposes 874 */ 875 union pipe_color_union coord; 876 get_texcoords(src, srclevel, srcbox->x, srcbox->y, 877 srcbox->x+width, srcbox->y+height, normalized, coord.f); 878 879 /* Draw. */ 880 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, 881 UTIL_BLITTER_ATTRIB_TEXCOORD, &coord); 882 } 883 break; 884 885 /* Draw the quad with the generic codepath. */ 886 default: 887 /* Set texture coordinates. */ 888 switch (src->target) { 889 case PIPE_TEXTURE_1D_ARRAY: 890 blitter_set_texcoords_1d_array(ctx, src, srclevel, srcbox->y, 891 srcbox->x, srcbox->x + width); 892 break; 893 894 case PIPE_TEXTURE_2D_ARRAY: 895 case PIPE_TEXTURE_3D: 896 blitter_set_texcoords_3d(ctx, src, srclevel, srcbox->z, 897 srcbox->x, srcbox->y, 898 srcbox->x + width, srcbox->y + height, 899 src->target == PIPE_TEXTURE_3D); 900 break; 901 902 case PIPE_TEXTURE_CUBE: 903 blitter_set_texcoords_cube(ctx, src, srclevel, srcbox->z, 904 srcbox->x, srcbox->y, 905 srcbox->x + width, srcbox->y + height); 906 break; 907 908 default: 909 assert(0); 910 } 911 912 /* Draw. */ 913 blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0); 914 ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf, 915 0, ctx->vbuf->width0); 916 util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0, 917 PIPE_PRIM_TRIANGLE_FAN, 4, 2); 918 break; 919 } 920 921 blitter_restore_CSOs(ctx); 922 923 pipe_surface_reference(&dstsurf, NULL); 924 pipe_sampler_view_reference(&view, NULL); 925} 926 927/* Clear a region of a color surface to a constant value. */ 928void util_blitter_clear_render_target(struct blitter_context *blitter, 929 struct pipe_surface *dstsurf, 930 const union pipe_color_union *color, 931 unsigned dstx, unsigned dsty, 932 unsigned width, unsigned height) 933{ 934 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 935 struct pipe_context *pipe = ctx->base.pipe; 936 struct pipe_framebuffer_state fb_state; 937 938 assert(dstsurf->texture); 939 if (!dstsurf->texture) 940 return; 941 942 /* check the saved state */ 943 blitter_check_saved_CSOs(ctx); 944 assert(blitter->saved_fb_state.nr_cbufs != ~0); 945 946 /* bind CSOs */ 947 pipe->bind_blend_state(pipe, ctx->blend_write_color); 948 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 949 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 950 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1)); 951 pipe->bind_vs_state(pipe, ctx->vs); 952 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 953 954 /* set a framebuffer state */ 955 fb_state.width = dstsurf->width; 956 fb_state.height = dstsurf->height; 957 fb_state.nr_cbufs = 1; 958 fb_state.cbufs[0] = dstsurf; 959 fb_state.zsbuf = 0; 960 pipe->set_framebuffer_state(pipe, &fb_state); 961 962 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); 963 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, 964 UTIL_BLITTER_ATTRIB_COLOR, color); 965 blitter_restore_CSOs(ctx); 966} 967 968/* Clear a region of a depth stencil surface. */ 969void util_blitter_clear_depth_stencil(struct blitter_context *blitter, 970 struct pipe_surface *dstsurf, 971 unsigned clear_flags, 972 double depth, 973 unsigned stencil, 974 unsigned dstx, unsigned dsty, 975 unsigned width, unsigned height) 976{ 977 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 978 struct pipe_context *pipe = ctx->base.pipe; 979 struct pipe_framebuffer_state fb_state; 980 struct pipe_stencil_ref sr = { { 0 } }; 981 982 assert(dstsurf->texture); 983 if (!dstsurf->texture) 984 return; 985 986 /* check the saved state */ 987 blitter_check_saved_CSOs(ctx); 988 assert(blitter->saved_fb_state.nr_cbufs != ~0); 989 990 /* bind CSOs */ 991 pipe->bind_blend_state(pipe, ctx->blend_keep_color); 992 if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { 993 sr.ref_value[0] = stencil & 0xff; 994 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); 995 pipe->set_stencil_ref(pipe, &sr); 996 } 997 else if (clear_flags & PIPE_CLEAR_DEPTH) { 998 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); 999 } 1000 else if (clear_flags & PIPE_CLEAR_STENCIL) { 1001 sr.ref_value[0] = stencil & 0xff; 1002 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); 1003 pipe->set_stencil_ref(pipe, &sr); 1004 } 1005 else 1006 /* hmm that should be illegal probably, or make it a no-op somewhere */ 1007 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 1008 1009 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 1010 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0)); 1011 pipe->bind_vs_state(pipe, ctx->vs); 1012 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 1013 1014 /* set a framebuffer state */ 1015 fb_state.width = dstsurf->width; 1016 fb_state.height = dstsurf->height; 1017 fb_state.nr_cbufs = 0; 1018 fb_state.cbufs[0] = 0; 1019 fb_state.zsbuf = dstsurf; 1020 pipe->set_framebuffer_state(pipe, &fb_state); 1021 1022 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); 1023 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, depth, 1024 UTIL_BLITTER_ATTRIB_NONE, NULL); 1025 blitter_restore_CSOs(ctx); 1026} 1027 1028/* draw a rectangle across a region using a custom dsa stage - for r600g */ 1029void util_blitter_custom_depth_stencil(struct blitter_context *blitter, 1030 struct pipe_surface *zsurf, 1031 struct pipe_surface *cbsurf, 1032 void *dsa_stage, float depth) 1033{ 1034 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 1035 struct pipe_context *pipe = ctx->base.pipe; 1036 struct pipe_framebuffer_state fb_state; 1037 1038 assert(zsurf->texture); 1039 if (!zsurf->texture) 1040 return; 1041 1042 /* check the saved state */ 1043 blitter_check_saved_CSOs(ctx); 1044 assert(blitter->saved_fb_state.nr_cbufs != ~0); 1045 1046 /* bind CSOs */ 1047 pipe->bind_blend_state(pipe, ctx->blend_write_color); 1048 pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage); 1049 1050 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 1051 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0)); 1052 pipe->bind_vs_state(pipe, ctx->vs); 1053 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 1054 1055 /* set a framebuffer state */ 1056 fb_state.width = zsurf->width; 1057 fb_state.height = zsurf->height; 1058 fb_state.nr_cbufs = 1; 1059 if (cbsurf) { 1060 fb_state.cbufs[0] = cbsurf; 1061 fb_state.nr_cbufs = 1; 1062 } else { 1063 fb_state.cbufs[0] = NULL; 1064 fb_state.nr_cbufs = 0; 1065 } 1066 fb_state.zsbuf = zsurf; 1067 pipe->set_framebuffer_state(pipe, &fb_state); 1068 1069 blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height); 1070 blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth, 1071 UTIL_BLITTER_ATTRIB_NONE, NULL); 1072 blitter_restore_CSOs(ctx); 1073} 1074