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