u_blitter.c revision 2449695e822421fdcaf1c66dffc12d7d705ea69d
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, 30 * clear_depth_stencil, and 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 63 /* Constant state objects. */ 64 /* Vertex shaders. */ 65 void *vs; /**< Vertex shader which passes {pos, generic} to the output.*/ 66 void *vs_pos_only; /**< Vertex shader which passes pos 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 void *fs_col_int[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 91 /* Vertex elements states. */ 92 void *velem_state; 93 void *velem_uint_state; 94 void *velem_sint_state; 95 void *velem_state_readbuf; 96 97 /* Sampler state. */ 98 void *sampler_state; 99 100 /* Rasterizer state. */ 101 void *rs_state; 102 void *rs_discard_state; 103 104 /* Viewport state. */ 105 struct pipe_viewport_state viewport; 106 107 /* Destination surface dimensions. */ 108 unsigned dst_width; 109 unsigned dst_height; 110 111 boolean has_geometry_shader; 112 boolean vertex_has_integers; 113 boolean has_stream_out; 114}; 115 116static void blitter_draw_rectangle(struct blitter_context *blitter, 117 unsigned x, unsigned y, 118 unsigned width, unsigned height, 119 float depth, 120 enum blitter_attrib_type type, 121 const union pipe_color_union *attrib); 122 123 124struct blitter_context *util_blitter_create(struct pipe_context *pipe) 125{ 126 struct blitter_context_priv *ctx; 127 struct pipe_blend_state blend; 128 struct pipe_depth_stencil_alpha_state dsa; 129 struct pipe_rasterizer_state rs_state; 130 struct pipe_sampler_state sampler_state; 131 struct pipe_vertex_element velem[2]; 132 unsigned i; 133 134 ctx = CALLOC_STRUCT(blitter_context_priv); 135 if (!ctx) 136 return NULL; 137 138 ctx->base.pipe = pipe; 139 ctx->base.draw_rectangle = blitter_draw_rectangle; 140 141 /* init state objects for them to be considered invalid */ 142 ctx->base.saved_blend_state = INVALID_PTR; 143 ctx->base.saved_dsa_state = INVALID_PTR; 144 ctx->base.saved_rs_state = INVALID_PTR; 145 ctx->base.saved_fs = INVALID_PTR; 146 ctx->base.saved_vs = INVALID_PTR; 147 ctx->base.saved_gs = INVALID_PTR; 148 ctx->base.saved_velem_state = INVALID_PTR; 149 ctx->base.saved_fb_state.nr_cbufs = ~0; 150 ctx->base.saved_num_sampler_views = ~0; 151 ctx->base.saved_num_sampler_states = ~0; 152 ctx->base.saved_num_vertex_buffers = ~0; 153 ctx->base.saved_num_so_targets = ~0; 154 155 ctx->has_geometry_shader = 156 pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY, 157 PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0; 158 ctx->vertex_has_integers = 159 pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_VERTEX, 160 PIPE_SHADER_CAP_INTEGERS); 161 ctx->has_stream_out = 162 pipe->screen->get_param(pipe->screen, 163 PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0; 164 165 /* blend state objects */ 166 memset(&blend, 0, sizeof(blend)); 167 ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend); 168 169 blend.rt[0].colormask = PIPE_MASK_RGBA; 170 ctx->blend_write_color = pipe->create_blend_state(pipe, &blend); 171 172 /* depth stencil alpha state objects */ 173 memset(&dsa, 0, sizeof(dsa)); 174 ctx->dsa_keep_depth_stencil = 175 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 176 177 dsa.depth.enabled = 1; 178 dsa.depth.writemask = 1; 179 dsa.depth.func = PIPE_FUNC_ALWAYS; 180 ctx->dsa_write_depth_keep_stencil = 181 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 182 183 dsa.stencil[0].enabled = 1; 184 dsa.stencil[0].func = PIPE_FUNC_ALWAYS; 185 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; 186 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; 187 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; 188 dsa.stencil[0].valuemask = 0xff; 189 dsa.stencil[0].writemask = 0xff; 190 ctx->dsa_write_depth_stencil = 191 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 192 193 dsa.depth.enabled = 0; 194 dsa.depth.writemask = 0; 195 ctx->dsa_keep_depth_write_stencil = 196 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 197 198 /* sampler state */ 199 memset(&sampler_state, 0, sizeof(sampler_state)); 200 sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 201 sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 202 sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 203 sampler_state.normalized_coords = 1; 204 ctx->sampler_state = pipe->create_sampler_state(pipe, &sampler_state); 205 206 /* rasterizer state */ 207 memset(&rs_state, 0, sizeof(rs_state)); 208 rs_state.cull_face = PIPE_FACE_NONE; 209 rs_state.gl_rasterization_rules = 1; 210 rs_state.flatshade = 1; 211 rs_state.depth_clip = 1; 212 ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); 213 214 if (ctx->has_stream_out) { 215 rs_state.rasterizer_discard = 1; 216 ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state); 217 } 218 219 /* vertex elements states */ 220 memset(&velem[0], 0, sizeof(velem[0]) * 2); 221 for (i = 0; i < 2; i++) { 222 velem[i].src_offset = i * 4 * sizeof(float); 223 velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 224 } 225 ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]); 226 227 if (ctx->vertex_has_integers) { 228 memset(&velem[0], 0, sizeof(velem[0]) * 2); 229 velem[0].src_offset = 0; 230 velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 231 velem[1].src_offset = 4 * sizeof(float); 232 velem[1].src_format = PIPE_FORMAT_R32G32B32A32_SINT; 233 ctx->velem_sint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]); 234 235 memset(&velem[0], 0, sizeof(velem[0]) * 2); 236 velem[0].src_offset = 0; 237 velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 238 velem[1].src_offset = 4 * sizeof(float); 239 velem[1].src_format = PIPE_FORMAT_R32G32B32A32_UINT; 240 ctx->velem_uint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]); 241 } 242 243 if (ctx->has_stream_out) { 244 velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 245 ctx->velem_state_readbuf = pipe->create_vertex_elements_state(pipe, 1, &velem[0]); 246 } 247 248 /* fragment shaders are created on-demand */ 249 250 /* vertex shaders */ 251 { 252 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, 253 TGSI_SEMANTIC_GENERIC }; 254 const uint semantic_indices[] = { 0, 0 }; 255 ctx->vs = 256 util_make_vertex_passthrough_shader(pipe, 2, semantic_names, 257 semantic_indices); 258 } 259 if (ctx->has_stream_out) { 260 struct pipe_stream_output_info so; 261 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION }; 262 const uint semantic_indices[] = { 0 }; 263 264 memset(&so, 0, sizeof(so)); 265 so.num_outputs = 1; 266 so.output[0].num_components = 4; 267 so.stride[0] = 4; 268 269 ctx->vs_pos_only = 270 util_make_vertex_passthrough_shader_with_so(pipe, 1, semantic_names, 271 semantic_indices, &so); 272 } 273 274 /* set invariant vertex coordinates */ 275 for (i = 0; i < 4; i++) 276 ctx->vertices[i][0][3] = 1; /*v.w*/ 277 278 /* create the vertex buffer */ 279 ctx->vbuf = pipe_user_buffer_create(ctx->base.pipe->screen, 280 ctx->vertices, 281 sizeof(ctx->vertices), 282 PIPE_BIND_VERTEX_BUFFER); 283 284 return &ctx->base; 285} 286 287void util_blitter_destroy(struct blitter_context *blitter) 288{ 289 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 290 struct pipe_context *pipe = blitter->pipe; 291 int i; 292 293 pipe->delete_blend_state(pipe, ctx->blend_write_color); 294 pipe->delete_blend_state(pipe, ctx->blend_keep_color); 295 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 296 pipe->delete_depth_stencil_alpha_state(pipe, 297 ctx->dsa_write_depth_keep_stencil); 298 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); 299 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); 300 301 pipe->delete_rasterizer_state(pipe, ctx->rs_state); 302 if (ctx->rs_discard_state) 303 pipe->delete_rasterizer_state(pipe, ctx->rs_discard_state); 304 pipe->delete_vs_state(pipe, ctx->vs); 305 if (ctx->vs_pos_only) 306 pipe->delete_vs_state(pipe, ctx->vs_pos_only); 307 pipe->delete_vertex_elements_state(pipe, ctx->velem_state); 308 if (ctx->vertex_has_integers) { 309 pipe->delete_vertex_elements_state(pipe, ctx->velem_sint_state); 310 pipe->delete_vertex_elements_state(pipe, ctx->velem_uint_state); 311 } 312 if (ctx->velem_state_readbuf) 313 pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf); 314 315 for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { 316 if (ctx->fs_texfetch_col[i]) 317 pipe->delete_fs_state(pipe, ctx->fs_texfetch_col[i]); 318 if (ctx->fs_texfetch_depth[i]) 319 pipe->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]); 320 } 321 322 for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++) { 323 if (ctx->fs_col[i]) 324 pipe->delete_fs_state(pipe, ctx->fs_col[i]); 325 if (ctx->fs_col_int[i]) 326 pipe->delete_fs_state(pipe, ctx->fs_col_int[i]); 327 } 328 329 pipe->delete_sampler_state(pipe, ctx->sampler_state); 330 pipe_resource_reference(&ctx->vbuf, NULL); 331 FREE(ctx); 332} 333 334static void blitter_set_running_flag(struct blitter_context_priv *ctx) 335{ 336 if (ctx->base.running) { 337 _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n", 338 __LINE__); 339 } 340 ctx->base.running = TRUE; 341} 342 343static void blitter_unset_running_flag(struct blitter_context_priv *ctx) 344{ 345 if (!ctx->base.running) { 346 _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n", 347 __LINE__); 348 } 349 ctx->base.running = FALSE; 350} 351 352static void blitter_check_saved_vertex_states(struct blitter_context_priv *ctx) 353{ 354 assert(ctx->base.saved_num_vertex_buffers != ~0 && 355 ctx->base.saved_velem_state != INVALID_PTR && 356 ctx->base.saved_vs != INVALID_PTR && 357 (!ctx->has_geometry_shader || ctx->base.saved_gs != INVALID_PTR) && 358 (!ctx->has_stream_out || ctx->base.saved_num_so_targets != ~0) && 359 ctx->base.saved_rs_state != INVALID_PTR); 360} 361 362static void blitter_restore_vertex_states(struct blitter_context_priv *ctx) 363{ 364 struct pipe_context *pipe = ctx->base.pipe; 365 unsigned i; 366 367 /* Vertex buffers. */ 368 pipe->set_vertex_buffers(pipe, 369 ctx->base.saved_num_vertex_buffers, 370 ctx->base.saved_vertex_buffers); 371 372 for (i = 0; i < ctx->base.saved_num_vertex_buffers; i++) { 373 if (ctx->base.saved_vertex_buffers[i].buffer) { 374 pipe_resource_reference(&ctx->base.saved_vertex_buffers[i].buffer, 375 NULL); 376 } 377 } 378 ctx->base.saved_num_vertex_buffers = ~0; 379 380 /* Vertex elements. */ 381 pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state); 382 ctx->base.saved_velem_state = INVALID_PTR; 383 384 /* Vertex shader. */ 385 pipe->bind_vs_state(pipe, ctx->base.saved_vs); 386 ctx->base.saved_vs = INVALID_PTR; 387 388 /* Geometry shader. */ 389 if (ctx->has_geometry_shader) { 390 pipe->bind_gs_state(pipe, ctx->base.saved_gs); 391 ctx->base.saved_gs = INVALID_PTR; 392 } 393 394 /* Stream outputs. */ 395 if (ctx->has_stream_out) { 396 pipe->set_stream_output_targets(pipe, 397 ctx->base.saved_num_so_targets, 398 ctx->base.saved_so_targets, ~0); 399 400 for (i = 0; i < ctx->base.saved_num_so_targets; i++) 401 pipe_so_target_reference(&ctx->base.saved_so_targets[i], NULL); 402 403 ctx->base.saved_num_so_targets = ~0; 404 } 405 406 /* Rasterizer. */ 407 pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state); 408 ctx->base.saved_rs_state = INVALID_PTR; 409} 410 411static void blitter_check_saved_fragment_states(struct blitter_context_priv *ctx) 412{ 413 assert(ctx->base.saved_fs != INVALID_PTR && 414 ctx->base.saved_dsa_state != INVALID_PTR && 415 ctx->base.saved_blend_state != INVALID_PTR); 416} 417 418static void blitter_restore_fragment_states(struct blitter_context_priv *ctx) 419{ 420 struct pipe_context *pipe = ctx->base.pipe; 421 422 /* Fragment shader. */ 423 pipe->bind_fs_state(pipe, ctx->base.saved_fs); 424 ctx->base.saved_fs = INVALID_PTR; 425 426 /* Depth, stencil, alpha. */ 427 pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state); 428 ctx->base.saved_dsa_state = INVALID_PTR; 429 430 /* Blend state. */ 431 pipe->bind_blend_state(pipe, ctx->base.saved_blend_state); 432 ctx->base.saved_blend_state = INVALID_PTR; 433 434 /* Miscellaneous states. */ 435 /* XXX check whether these are saved and whether they need to be restored 436 * (depending on the operation) */ 437 pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref); 438 pipe->set_viewport_state(pipe, &ctx->base.saved_viewport); 439} 440 441static void blitter_check_saved_fb_state(struct blitter_context_priv *ctx) 442{ 443 assert(ctx->base.saved_fb_state.nr_cbufs != ~0); 444} 445 446static void blitter_restore_fb_state(struct blitter_context_priv *ctx) 447{ 448 struct pipe_context *pipe = ctx->base.pipe; 449 450 pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state); 451 util_unreference_framebuffer_state(&ctx->base.saved_fb_state); 452} 453 454static void blitter_check_saved_textures(struct blitter_context_priv *ctx) 455{ 456 assert(ctx->base.saved_num_sampler_states != ~0 && 457 ctx->base.saved_num_sampler_views != ~0); 458} 459 460static void blitter_restore_textures(struct blitter_context_priv *ctx) 461{ 462 struct pipe_context *pipe = ctx->base.pipe; 463 unsigned i; 464 465 /* Fragment sampler states. */ 466 pipe->bind_fragment_sampler_states(pipe, 467 ctx->base.saved_num_sampler_states, 468 ctx->base.saved_sampler_states); 469 ctx->base.saved_num_sampler_states = ~0; 470 471 /* Fragment sampler views. */ 472 pipe->set_fragment_sampler_views(pipe, 473 ctx->base.saved_num_sampler_views, 474 ctx->base.saved_sampler_views); 475 476 for (i = 0; i < ctx->base.saved_num_sampler_views; i++) 477 pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i], NULL); 478 479 ctx->base.saved_num_sampler_views = ~0; 480} 481 482static void blitter_set_rectangle(struct blitter_context_priv *ctx, 483 unsigned x1, unsigned y1, 484 unsigned x2, unsigned y2, 485 float depth) 486{ 487 int i; 488 489 /* set vertex positions */ 490 ctx->vertices[0][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v0.x*/ 491 ctx->vertices[0][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v0.y*/ 492 493 ctx->vertices[1][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v1.x*/ 494 ctx->vertices[1][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v1.y*/ 495 496 ctx->vertices[2][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v2.x*/ 497 ctx->vertices[2][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v2.y*/ 498 499 ctx->vertices[3][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v3.x*/ 500 ctx->vertices[3][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v3.y*/ 501 502 for (i = 0; i < 4; i++) 503 ctx->vertices[i][0][2] = depth; /*z*/ 504 505 /* viewport */ 506 ctx->viewport.scale[0] = 0.5f * ctx->dst_width; 507 ctx->viewport.scale[1] = 0.5f * ctx->dst_height; 508 ctx->viewport.scale[2] = 1.0f; 509 ctx->viewport.scale[3] = 1.0f; 510 ctx->viewport.translate[0] = 0.5f * ctx->dst_width; 511 ctx->viewport.translate[1] = 0.5f * ctx->dst_height; 512 ctx->viewport.translate[2] = 0.0f; 513 ctx->viewport.translate[3] = 0.0f; 514 ctx->base.pipe->set_viewport_state(ctx->base.pipe, &ctx->viewport); 515} 516 517static void blitter_set_clear_color(struct blitter_context_priv *ctx, 518 const union pipe_color_union *color) 519{ 520 int i; 521 522 if (color) { 523 for (i = 0; i < 4; i++) { 524 uint32_t *uiverts = (uint32_t *)ctx->vertices[i][1]; 525 uiverts[0] = color->ui[0]; 526 uiverts[1] = color->ui[1]; 527 uiverts[2] = color->ui[2]; 528 uiverts[3] = color->ui[3]; 529 } 530 } else { 531 for (i = 0; i < 4; i++) { 532 ctx->vertices[i][1][0] = 0; 533 ctx->vertices[i][1][1] = 0; 534 ctx->vertices[i][1][2] = 0; 535 ctx->vertices[i][1][3] = 0; 536 } 537 } 538} 539 540static void get_texcoords(struct pipe_sampler_view *src, 541 unsigned src_width0, unsigned src_height0, 542 unsigned x1, unsigned y1, 543 unsigned x2, unsigned y2, 544 float out[4]) 545{ 546 struct pipe_resource *tex = src->texture; 547 unsigned level = src->u.tex.first_level; 548 boolean normalized = tex->target != PIPE_TEXTURE_RECT; 549 550 if (normalized) { 551 out[0] = x1 / (float)u_minify(src_width0, level); 552 out[1] = y1 / (float)u_minify(src_height0, level); 553 out[2] = x2 / (float)u_minify(src_width0, level); 554 out[3] = y2 / (float)u_minify(src_height0, level); 555 } else { 556 out[0] = x1; 557 out[1] = y1; 558 out[2] = x2; 559 out[3] = y2; 560 } 561} 562 563static void set_texcoords_in_vertices(const float coord[4], 564 float *out, unsigned stride) 565{ 566 out[0] = coord[0]; /*t0.s*/ 567 out[1] = coord[1]; /*t0.t*/ 568 out += stride; 569 out[0] = coord[2]; /*t1.s*/ 570 out[1] = coord[1]; /*t1.t*/ 571 out += stride; 572 out[0] = coord[2]; /*t2.s*/ 573 out[1] = coord[3]; /*t2.t*/ 574 out += stride; 575 out[0] = coord[0]; /*t3.s*/ 576 out[1] = coord[3]; /*t3.t*/ 577} 578 579static void blitter_set_texcoords(struct blitter_context_priv *ctx, 580 struct pipe_sampler_view *src, 581 unsigned src_width0, unsigned src_height0, 582 unsigned layer, 583 unsigned x1, unsigned y1, 584 unsigned x2, unsigned y2) 585{ 586 unsigned i; 587 float coord[4]; 588 float face_coord[4][2]; 589 590 get_texcoords(src, src_width0, src_height0, x1, y1, x2, y2, coord); 591 592 if (src->texture->target == PIPE_TEXTURE_CUBE) { 593 set_texcoords_in_vertices(coord, &face_coord[0][0], 2); 594 util_map_texcoords2d_onto_cubemap(layer, 595 /* pointer, stride in floats */ 596 &face_coord[0][0], 2, 597 &ctx->vertices[0][1][0], 8); 598 } else { 599 set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8); 600 } 601 602 /* Set the layer. */ 603 switch (src->texture->target) { 604 case PIPE_TEXTURE_3D: 605 { 606 float r = layer / (float)u_minify(src->texture->depth0, 607 src->u.tex.first_level); 608 for (i = 0; i < 4; i++) 609 ctx->vertices[i][1][2] = r; /*r*/ 610 } 611 break; 612 613 case PIPE_TEXTURE_1D_ARRAY: 614 for (i = 0; i < 4; i++) 615 ctx->vertices[i][1][1] = layer; /*t*/ 616 break; 617 618 case PIPE_TEXTURE_2D_ARRAY: 619 for (i = 0; i < 4; i++) 620 ctx->vertices[i][1][2] = layer; /*r*/ 621 break; 622 623 default:; 624 } 625} 626 627static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx, 628 unsigned width, unsigned height) 629{ 630 ctx->dst_width = width; 631 ctx->dst_height = height; 632} 633 634static INLINE 635void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs, 636 boolean int_format) 637{ 638 struct pipe_context *pipe = ctx->base.pipe; 639 640 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); 641 642 if (int_format) { 643 if (!ctx->fs_col_int[num_cbufs]) 644 ctx->fs_col_int[num_cbufs] = 645 util_make_fragment_cloneinput_shader(pipe, num_cbufs, 646 TGSI_SEMANTIC_GENERIC, 647 TGSI_INTERPOLATE_CONSTANT); 648 return ctx->fs_col_int[num_cbufs]; 649 } else { 650 if (!ctx->fs_col[num_cbufs]) 651 ctx->fs_col[num_cbufs] = 652 util_make_fragment_cloneinput_shader(pipe, num_cbufs, 653 TGSI_SEMANTIC_GENERIC, 654 TGSI_INTERPOLATE_LINEAR); 655 return ctx->fs_col[num_cbufs]; 656 } 657} 658 659/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */ 660static unsigned 661pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target) 662{ 663 switch (pipe_tex_target) { 664 case PIPE_TEXTURE_1D: 665 return TGSI_TEXTURE_1D; 666 case PIPE_TEXTURE_2D: 667 return TGSI_TEXTURE_2D; 668 case PIPE_TEXTURE_RECT: 669 return TGSI_TEXTURE_RECT; 670 case PIPE_TEXTURE_3D: 671 return TGSI_TEXTURE_3D; 672 case PIPE_TEXTURE_CUBE: 673 return TGSI_TEXTURE_CUBE; 674 case PIPE_TEXTURE_1D_ARRAY: 675 return TGSI_TEXTURE_1D_ARRAY; 676 case PIPE_TEXTURE_2D_ARRAY: 677 return TGSI_TEXTURE_2D_ARRAY; 678 default: 679 assert(0 && "unexpected texture target"); 680 return TGSI_TEXTURE_UNKNOWN; 681 } 682} 683 684 685static INLINE 686void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, 687 unsigned tex_target) 688{ 689 struct pipe_context *pipe = ctx->base.pipe; 690 691 assert(tex_target < PIPE_MAX_TEXTURE_TYPES); 692 693 /* Create the fragment shader on-demand. */ 694 if (!ctx->fs_texfetch_col[tex_target]) { 695 unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target); 696 697 ctx->fs_texfetch_col[tex_target] = 698 util_make_fragment_tex_shader(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR); 699 } 700 701 return ctx->fs_texfetch_col[tex_target]; 702} 703 704static INLINE 705void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx, 706 unsigned tex_target) 707{ 708 struct pipe_context *pipe = ctx->base.pipe; 709 710 assert(tex_target < PIPE_MAX_TEXTURE_TYPES); 711 712 /* Create the fragment shader on-demand. */ 713 if (!ctx->fs_texfetch_depth[tex_target]) { 714 unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target); 715 716 ctx->fs_texfetch_depth[tex_target] = 717 util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex, 718 TGSI_INTERPOLATE_LINEAR); 719 } 720 721 return ctx->fs_texfetch_depth[tex_target]; 722} 723 724static void blitter_draw_rectangle(struct blitter_context *blitter, 725 unsigned x1, unsigned y1, 726 unsigned x2, unsigned y2, 727 float depth, 728 enum blitter_attrib_type type, 729 const union pipe_color_union *attrib) 730{ 731 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 732 733 switch (type) { 734 case UTIL_BLITTER_ATTRIB_COLOR: 735 blitter_set_clear_color(ctx, attrib); 736 break; 737 738 case UTIL_BLITTER_ATTRIB_TEXCOORD: 739 set_texcoords_in_vertices(attrib->f, &ctx->vertices[0][1][0], 8); 740 break; 741 742 default:; 743 } 744 745 blitter_set_rectangle(ctx, x1, y1, x2, y2, depth); 746 ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf, 747 0, ctx->vbuf->width0); 748 util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0, 749 PIPE_PRIM_TRIANGLE_FAN, 4, 2); 750} 751 752static void util_blitter_clear_custom(struct blitter_context *blitter, 753 unsigned width, unsigned height, 754 unsigned num_cbufs, 755 unsigned clear_buffers, 756 enum pipe_format cbuf_format, 757 const union pipe_color_union *color, 758 double depth, unsigned stencil, 759 void *custom_blend, void *custom_dsa) 760{ 761 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 762 struct pipe_context *pipe = ctx->base.pipe; 763 struct pipe_stencil_ref sr = { { 0 } }; 764 boolean int_format = util_format_is_pure_integer(cbuf_format); 765 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); 766 767 blitter_set_running_flag(ctx); 768 blitter_check_saved_vertex_states(ctx); 769 blitter_check_saved_fragment_states(ctx); 770 771 /* bind states */ 772 if (custom_blend) { 773 pipe->bind_blend_state(pipe, custom_blend); 774 } else if (clear_buffers & PIPE_CLEAR_COLOR) { 775 pipe->bind_blend_state(pipe, ctx->blend_write_color); 776 } else { 777 pipe->bind_blend_state(pipe, ctx->blend_keep_color); 778 } 779 780 if (custom_dsa) { 781 pipe->bind_depth_stencil_alpha_state(pipe, custom_dsa); 782 } else if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { 783 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); 784 } else if (clear_buffers & PIPE_CLEAR_DEPTH) { 785 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); 786 } else if (clear_buffers & PIPE_CLEAR_STENCIL) { 787 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); 788 } else { 789 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 790 } 791 792 sr.ref_value[0] = stencil & 0xff; 793 pipe->set_stencil_ref(pipe, &sr); 794 795 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 796 if (util_format_is_pure_sint(cbuf_format)) { 797 pipe->bind_vertex_elements_state(pipe, ctx->velem_sint_state); 798 } else if (util_format_is_pure_uint(cbuf_format)) { 799 pipe->bind_vertex_elements_state(pipe, ctx->velem_uint_state); 800 } else { 801 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 802 } 803 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs, int_format)); 804 pipe->bind_vs_state(pipe, ctx->vs); 805 if (ctx->has_geometry_shader) 806 pipe->bind_gs_state(pipe, NULL); 807 808 blitter_set_dst_dimensions(ctx, width, height); 809 blitter->draw_rectangle(blitter, 0, 0, width, height, depth, 810 UTIL_BLITTER_ATTRIB_COLOR, color); 811 812 blitter_restore_vertex_states(ctx); 813 blitter_restore_fragment_states(ctx); 814 blitter_unset_running_flag(ctx); 815} 816 817void util_blitter_clear(struct blitter_context *blitter, 818 unsigned width, unsigned height, 819 unsigned num_cbufs, 820 unsigned clear_buffers, 821 enum pipe_format cbuf_format, 822 const union pipe_color_union *color, 823 double depth, unsigned stencil) 824{ 825 util_blitter_clear_custom(blitter, width, height, num_cbufs, 826 clear_buffers, cbuf_format, color, depth, stencil, 827 NULL, NULL); 828} 829 830void util_blitter_clear_depth_custom(struct blitter_context *blitter, 831 unsigned width, unsigned height, 832 double depth, void *custom_dsa) 833{ 834 static const union pipe_color_union color; 835 util_blitter_clear_custom(blitter, width, height, 0, 836 0, PIPE_FORMAT_NONE, &color, depth, 0, NULL, custom_dsa); 837} 838 839static 840boolean is_overlap(unsigned sx1, unsigned sx2, unsigned sy1, unsigned sy2, 841 unsigned dx1, unsigned dx2, unsigned dy1, unsigned dy2) 842{ 843 return sx1 < dx2 && sx2 > dx1 && sy1 < dy2 && sy2 > dy1; 844} 845 846void util_blitter_default_dst_texture(struct pipe_surface *dst_templ, 847 struct pipe_resource *dst, 848 unsigned dstlevel, 849 unsigned dstz, 850 const struct pipe_box *srcbox) 851{ 852 memset(dst_templ, 0, sizeof(*dst_templ)); 853 dst_templ->format = dst->format; 854 if (util_format_is_depth_or_stencil(dst->format)) { 855 dst_templ->usage = PIPE_BIND_DEPTH_STENCIL; 856 } else { 857 dst_templ->usage = PIPE_BIND_RENDER_TARGET; 858 } 859 dst_templ->format = util_format_linear(dst->format); 860 dst_templ->u.tex.level = dstlevel; 861 dst_templ->u.tex.first_layer = dstz; 862 dst_templ->u.tex.last_layer = dstz + srcbox->depth - 1; 863} 864 865void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ, 866 struct pipe_resource *src, 867 unsigned srclevel) 868{ 869 memset(src_templ, 0, sizeof(*src_templ)); 870 src_templ->format = util_format_linear(src->format); 871 src_templ->u.tex.first_level = srclevel; 872 src_templ->u.tex.last_level = srclevel; 873 src_templ->u.tex.first_layer = 0; 874 src_templ->u.tex.last_layer = 875 src->target == PIPE_TEXTURE_3D ? src->depth0 - 1 876 : src->array_size - 1; 877 src_templ->swizzle_r = PIPE_SWIZZLE_RED; 878 src_templ->swizzle_g = PIPE_SWIZZLE_GREEN; 879 src_templ->swizzle_b = PIPE_SWIZZLE_BLUE; 880 src_templ->swizzle_a = PIPE_SWIZZLE_ALPHA; 881} 882 883void util_blitter_copy_texture(struct blitter_context *blitter, 884 struct pipe_resource *dst, 885 unsigned dstlevel, 886 unsigned dstx, unsigned dsty, unsigned dstz, 887 struct pipe_resource *src, 888 unsigned srclevel, 889 const struct pipe_box *srcbox, 890 boolean ignore_stencil) 891{ 892 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 893 struct pipe_context *pipe = ctx->base.pipe; 894 struct pipe_screen *screen = pipe->screen; 895 struct pipe_surface *dst_view, dst_templ; 896 struct pipe_sampler_view src_templ, *src_view; 897 unsigned bind; 898 boolean is_stencil, is_depth; 899 900 /* Give up if textures are not set. */ 901 assert(dst && src); 902 if (!dst || !src) 903 return; 904 905 assert(src->target < PIPE_MAX_TEXTURE_TYPES); 906 907 /* Is this a ZS format? */ 908 is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0; 909 is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0; 910 911 if (is_depth || is_stencil) 912 bind = PIPE_BIND_DEPTH_STENCIL; 913 else 914 bind = PIPE_BIND_RENDER_TARGET; 915 916 /* Check if we can sample from and render to the surfaces. */ 917 /* (assuming copying a stencil buffer is not possible) */ 918 if ((!ignore_stencil && is_stencil) || 919 !screen->is_format_supported(screen, dst->format, dst->target, 920 dst->nr_samples, bind) || 921 !screen->is_format_supported(screen, src->format, src->target, 922 src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) { 923 blitter_set_running_flag(ctx); 924 util_resource_copy_region(pipe, dst, dstlevel, dstx, dsty, dstz, 925 src, srclevel, srcbox); 926 blitter_unset_running_flag(ctx); 927 return; 928 } 929 930 /* Initialize the surface. */ 931 util_blitter_default_dst_texture(&dst_templ, dst, dstlevel, dstz, srcbox); 932 dst_view = pipe->create_surface(pipe, dst, &dst_templ); 933 934 /* Initialize the sampler view. */ 935 util_blitter_default_src_texture(&src_templ, src, srclevel); 936 src_view = pipe->create_sampler_view(pipe, src, &src_templ); 937 938 /* Copy. */ 939 util_blitter_copy_texture_view(blitter, dst_view, dstx, dsty, src_view, 940 srcbox, src->width0, src->height0); 941 942 pipe_surface_reference(&dst_view, NULL); 943 pipe_sampler_view_reference(&src_view, NULL); 944} 945 946void util_blitter_copy_texture_view(struct blitter_context *blitter, 947 struct pipe_surface *dst, 948 unsigned dstx, unsigned dsty, 949 struct pipe_sampler_view *src, 950 const struct pipe_box *srcbox, 951 unsigned src_width0, unsigned src_height0) 952{ 953 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 954 struct pipe_context *pipe = ctx->base.pipe; 955 struct pipe_framebuffer_state fb_state; 956 enum pipe_texture_target src_target = src->texture->target; 957 unsigned width = srcbox->width; 958 unsigned height = srcbox->height; 959 960 /* Sanity checks. */ 961 if (dst->texture == src->texture && 962 dst->u.tex.level == src->u.tex.first_level) { 963 assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height, 964 dstx, dstx + width, dsty, dsty + height)); 965 } 966 /* XXX should handle 3d regions */ 967 assert(srcbox->depth == 1); 968 969 /* Check whether the states are properly saved. */ 970 blitter_set_running_flag(ctx); 971 blitter_check_saved_vertex_states(ctx); 972 blitter_check_saved_fragment_states(ctx); 973 blitter_check_saved_textures(ctx); 974 blitter_check_saved_fb_state(ctx); 975 976 /* Initialize framebuffer state. */ 977 fb_state.width = dst->width; 978 fb_state.height = dst->height; 979 980 if (util_format_is_depth_or_stencil(dst->format)) { 981 pipe->bind_blend_state(pipe, ctx->blend_keep_color); 982 pipe->bind_depth_stencil_alpha_state(pipe, 983 ctx->dsa_write_depth_keep_stencil); 984 pipe->bind_fs_state(pipe, 985 blitter_get_fs_texfetch_depth(ctx, src_target)); 986 987 fb_state.nr_cbufs = 0; 988 fb_state.zsbuf = dst; 989 } else { 990 pipe->bind_blend_state(pipe, ctx->blend_write_color); 991 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 992 pipe->bind_fs_state(pipe, 993 blitter_get_fs_texfetch_col(ctx, src_target)); 994 995 fb_state.nr_cbufs = 1; 996 fb_state.cbufs[0] = dst; 997 fb_state.zsbuf = 0; 998 } 999 1000 /* Set rasterizer state, shaders, and textures. */ 1001 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 1002 pipe->bind_vs_state(pipe, ctx->vs); 1003 if (ctx->has_geometry_shader) 1004 pipe->bind_gs_state(pipe, NULL); 1005 pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state); 1006 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 1007 pipe->set_fragment_sampler_views(pipe, 1, &src); 1008 pipe->set_framebuffer_state(pipe, &fb_state); 1009 1010 blitter_set_dst_dimensions(ctx, dst->width, dst->height); 1011 1012 switch (src_target) { 1013 /* Draw the quad with the draw_rectangle callback. */ 1014 case PIPE_TEXTURE_1D: 1015 case PIPE_TEXTURE_2D: 1016 case PIPE_TEXTURE_RECT: 1017 { 1018 /* Set texture coordinates. - use a pipe color union 1019 * for interface purposes. 1020 * XXX pipe_color_union is a wrong name since we use that to set 1021 * texture coordinates too. 1022 */ 1023 union pipe_color_union coord; 1024 get_texcoords(src, src_width0, src_height0, srcbox->x, srcbox->y, 1025 srcbox->x+width, srcbox->y+height, coord.f); 1026 1027 /* Draw. */ 1028 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, 1029 UTIL_BLITTER_ATTRIB_TEXCOORD, &coord); 1030 } 1031 break; 1032 1033 /* Draw the quad with the generic codepath. */ 1034 default: 1035 /* Set texture coordinates. */ 1036 switch (src_target) { 1037 case PIPE_TEXTURE_1D_ARRAY: 1038 case PIPE_TEXTURE_2D_ARRAY: 1039 case PIPE_TEXTURE_3D: 1040 case PIPE_TEXTURE_CUBE: 1041 blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z, 1042 srcbox->y, srcbox->x, 1043 srcbox->x + width, srcbox->y + height); 1044 break; 1045 1046 default: 1047 assert(0); 1048 } 1049 1050 /* Draw. */ 1051 blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0); 1052 ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf, 1053 0, ctx->vbuf->width0); 1054 util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0, 1055 PIPE_PRIM_TRIANGLE_FAN, 4, 2); 1056 break; 1057 } 1058 1059 blitter_restore_vertex_states(ctx); 1060 blitter_restore_fragment_states(ctx); 1061 blitter_restore_textures(ctx); 1062 blitter_restore_fb_state(ctx); 1063 blitter_unset_running_flag(ctx); 1064} 1065 1066/* Clear a region of a color surface to a constant value. */ 1067void util_blitter_clear_render_target(struct blitter_context *blitter, 1068 struct pipe_surface *dstsurf, 1069 const union pipe_color_union *color, 1070 unsigned dstx, unsigned dsty, 1071 unsigned width, unsigned height) 1072{ 1073 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 1074 struct pipe_context *pipe = ctx->base.pipe; 1075 struct pipe_framebuffer_state fb_state; 1076 1077 assert(dstsurf->texture); 1078 if (!dstsurf->texture) 1079 return; 1080 1081 /* check the saved state */ 1082 blitter_set_running_flag(ctx); 1083 blitter_check_saved_vertex_states(ctx); 1084 blitter_check_saved_fragment_states(ctx); 1085 blitter_check_saved_fb_state(ctx); 1086 1087 /* bind states */ 1088 pipe->bind_blend_state(pipe, ctx->blend_write_color); 1089 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 1090 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 1091 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); 1092 pipe->bind_vs_state(pipe, ctx->vs); 1093 if (ctx->has_geometry_shader) 1094 pipe->bind_gs_state(pipe, NULL); 1095 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 1096 1097 /* set a framebuffer state */ 1098 fb_state.width = dstsurf->width; 1099 fb_state.height = dstsurf->height; 1100 fb_state.nr_cbufs = 1; 1101 fb_state.cbufs[0] = dstsurf; 1102 fb_state.zsbuf = 0; 1103 pipe->set_framebuffer_state(pipe, &fb_state); 1104 1105 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); 1106 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, 1107 UTIL_BLITTER_ATTRIB_COLOR, color); 1108 1109 blitter_restore_vertex_states(ctx); 1110 blitter_restore_fragment_states(ctx); 1111 blitter_restore_fb_state(ctx); 1112 blitter_unset_running_flag(ctx); 1113} 1114 1115/* Clear a region of a depth stencil surface. */ 1116void util_blitter_clear_depth_stencil(struct blitter_context *blitter, 1117 struct pipe_surface *dstsurf, 1118 unsigned clear_flags, 1119 double depth, 1120 unsigned stencil, 1121 unsigned dstx, unsigned dsty, 1122 unsigned width, unsigned height) 1123{ 1124 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 1125 struct pipe_context *pipe = ctx->base.pipe; 1126 struct pipe_framebuffer_state fb_state; 1127 struct pipe_stencil_ref sr = { { 0 } }; 1128 1129 assert(dstsurf->texture); 1130 if (!dstsurf->texture) 1131 return; 1132 1133 /* check the saved state */ 1134 blitter_set_running_flag(ctx); 1135 blitter_check_saved_vertex_states(ctx); 1136 blitter_check_saved_fragment_states(ctx); 1137 blitter_check_saved_fb_state(ctx); 1138 1139 /* bind states */ 1140 pipe->bind_blend_state(pipe, ctx->blend_keep_color); 1141 if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { 1142 sr.ref_value[0] = stencil & 0xff; 1143 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); 1144 pipe->set_stencil_ref(pipe, &sr); 1145 } 1146 else if (clear_flags & PIPE_CLEAR_DEPTH) { 1147 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); 1148 } 1149 else if (clear_flags & PIPE_CLEAR_STENCIL) { 1150 sr.ref_value[0] = stencil & 0xff; 1151 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); 1152 pipe->set_stencil_ref(pipe, &sr); 1153 } 1154 else 1155 /* hmm that should be illegal probably, or make it a no-op somewhere */ 1156 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 1157 1158 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 1159 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE)); 1160 pipe->bind_vs_state(pipe, ctx->vs); 1161 if (ctx->has_geometry_shader) 1162 pipe->bind_gs_state(pipe, NULL); 1163 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 1164 1165 /* set a framebuffer state */ 1166 fb_state.width = dstsurf->width; 1167 fb_state.height = dstsurf->height; 1168 fb_state.nr_cbufs = 0; 1169 fb_state.cbufs[0] = 0; 1170 fb_state.zsbuf = dstsurf; 1171 pipe->set_framebuffer_state(pipe, &fb_state); 1172 1173 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); 1174 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, depth, 1175 UTIL_BLITTER_ATTRIB_NONE, NULL); 1176 1177 blitter_restore_vertex_states(ctx); 1178 blitter_restore_fragment_states(ctx); 1179 blitter_restore_fb_state(ctx); 1180 blitter_unset_running_flag(ctx); 1181} 1182 1183/* draw a rectangle across a region using a custom dsa stage - for r600g */ 1184void util_blitter_custom_depth_stencil(struct blitter_context *blitter, 1185 struct pipe_surface *zsurf, 1186 struct pipe_surface *cbsurf, 1187 void *dsa_stage, float depth) 1188{ 1189 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 1190 struct pipe_context *pipe = ctx->base.pipe; 1191 struct pipe_framebuffer_state fb_state; 1192 1193 assert(zsurf->texture); 1194 if (!zsurf->texture) 1195 return; 1196 1197 /* check the saved state */ 1198 blitter_set_running_flag(ctx); 1199 blitter_check_saved_vertex_states(ctx); 1200 blitter_check_saved_fragment_states(ctx); 1201 blitter_check_saved_fb_state(ctx); 1202 1203 /* bind states */ 1204 pipe->bind_blend_state(pipe, ctx->blend_write_color); 1205 pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage); 1206 1207 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 1208 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE)); 1209 pipe->bind_vs_state(pipe, ctx->vs); 1210 if (ctx->has_geometry_shader) 1211 pipe->bind_gs_state(pipe, NULL); 1212 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 1213 1214 /* set a framebuffer state */ 1215 fb_state.width = zsurf->width; 1216 fb_state.height = zsurf->height; 1217 fb_state.nr_cbufs = 1; 1218 if (cbsurf) { 1219 fb_state.cbufs[0] = cbsurf; 1220 fb_state.nr_cbufs = 1; 1221 } else { 1222 fb_state.cbufs[0] = NULL; 1223 fb_state.nr_cbufs = 0; 1224 } 1225 fb_state.zsbuf = zsurf; 1226 pipe->set_framebuffer_state(pipe, &fb_state); 1227 1228 blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height); 1229 blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth, 1230 UTIL_BLITTER_ATTRIB_NONE, NULL); 1231 1232 blitter_restore_vertex_states(ctx); 1233 blitter_restore_fragment_states(ctx); 1234 blitter_restore_fb_state(ctx); 1235 blitter_unset_running_flag(ctx); 1236} 1237 1238void util_blitter_copy_buffer(struct blitter_context *blitter, 1239 struct pipe_resource *dst, 1240 unsigned dstx, 1241 struct pipe_resource *src, 1242 unsigned srcx, 1243 unsigned size) 1244{ 1245 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 1246 struct pipe_context *pipe = ctx->base.pipe; 1247 struct pipe_vertex_buffer vb; 1248 struct pipe_stream_output_target *so_target; 1249 1250 /* Drivers not capable of Stream Out should not call this function 1251 * in the first place. */ 1252 assert(ctx->has_stream_out); 1253 1254 /* Some alignment is required. */ 1255 if (srcx % 4 != 0 || dstx % 4 != 0 || size % 16 != 0 || 1256 !ctx->has_stream_out) { 1257 struct pipe_box box; 1258 u_box_1d(srcx, size, &box); 1259 util_resource_copy_region(pipe, dst, 0, dstx, 0, 0, src, 0, &box); 1260 return; 1261 } 1262 1263 blitter_set_running_flag(ctx); 1264 blitter_check_saved_vertex_states(ctx); 1265 1266 vb.buffer = src; 1267 vb.buffer_offset = srcx; 1268 vb.stride = 4; 1269 1270 pipe->set_vertex_buffers(pipe, 1, &vb); 1271 pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf); 1272 pipe->bind_vs_state(pipe, ctx->vs_pos_only); 1273 if (ctx->has_geometry_shader) 1274 pipe->bind_gs_state(pipe, NULL); 1275 pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state); 1276 1277 so_target = pipe->create_stream_output_target(pipe, dst, dstx, size); 1278 pipe->set_stream_output_targets(pipe, 1, &so_target, 0); 1279 1280 util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 16); 1281 1282 blitter_restore_vertex_states(ctx); 1283 blitter_unset_running_flag(ctx); 1284 pipe_so_target_reference(&so_target, NULL); 1285} 1286