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