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