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