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