u_blitter.c revision 2a456dc123e8263de8e4666890a34f403faa9a39
12d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines/************************************************************************** 22d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines * 32d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines * Copyright 2009 Marek Olšák <maraeo@gmail.com> 42d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines * 55d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines * Permission is hereby granted, free of charge, to any person obtaining a 641f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * copy of this software and associated documentation files (the 741f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * "Software"), to deal in the Software without restriction, including 841f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * without limitation the rights to use, copy, modify, merge, publish, 941f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * distribute, sub license, and/or sell copies of the Software, and to 1041f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * permit persons to whom the Software is furnished to do so, subject to 1141f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * the following conditions: 1241f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * 1341f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * The above copyright notice and this permission notice (including the 1441f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * next paragraph) shall be included in all copies or substantial portions 1541f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * of the Software. 1641f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * 1741f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1841f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1941f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 2041f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 2155425eb7ad3f18a1f740e0e445bc79a012429766Alexey Samsonov * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 2255425eb7ad3f18a1f740e0e445bc79a012429766Alexey Samsonov * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 2355425eb7ad3f18a1f740e0e445bc79a012429766Alexey Samsonov * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24ed4c034955e33b999b37f735feec8a7c315a6e3dAlexander Potapenko * 2555425eb7ad3f18a1f740e0e445bc79a012429766Alexey Samsonov **************************************************************************/ 2655425eb7ad3f18a1f740e0e445bc79a012429766Alexey Samsonov 2755425eb7ad3f18a1f740e0e445bc79a012429766Alexey Samsonov/** 2855425eb7ad3f18a1f740e0e445bc79a012429766Alexey Samsonov * @file 2941f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * Blitter utility to facilitate acceleration of the clear, clear_render_target, clear_depth_stencil 3041f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * resource_copy_region functions. 3141f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * 3241f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov * @author Marek Olšák 3341f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov */ 3441f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov 3541f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov#include "pipe/p_context.h" 3641f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov#include "pipe/p_defines.h" 3741f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov#include "util/u_inlines.h" 3841f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov#include "pipe/p_shader_tokens.h" 3941f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov#include "pipe/p_state.h" 4041f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov 4141f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov#include "util/u_format.h" 4241f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov#include "util/u_memory.h" 4341f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov#include "util/u_math.h" 4441f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov#include "util/u_blitter.h" 45ed936c1d3a8db321b45d2e249159ec48c6450043Alexey Samsonov#include "util/u_draw_quad.h" 46ed4c034955e33b999b37f735feec8a7c315a6e3dAlexander Potapenko#include "util/u_sampler.h" 4755425eb7ad3f18a1f740e0e445bc79a012429766Alexey Samsonov#include "util/u_simple_shaders.h" 48d4228010624f7c6fa69934add3f9da46cc6b6918Alexander Potapenko#include "util/u_surface.h" 49d4228010624f7c6fa69934add3f9da46cc6b6918Alexander Potapenko#include "util/u_texture.h" 50ed936c1d3a8db321b45d2e249159ec48c6450043Alexey Samsonov 5141f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov#define INVALID_PTR ((void*)~0) 5241f85b9e6a88f801955d99c8a8233b97e64c51ffAlexey Samsonov 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 boolean running; 109}; 110 111static void blitter_draw_rectangle(struct blitter_context *blitter, 112 unsigned x, unsigned y, 113 unsigned width, unsigned height, 114 float depth, 115 enum blitter_attrib_type type, 116 const float attrib[4]); 117 118 119struct blitter_context *util_blitter_create(struct pipe_context *pipe) 120{ 121 struct blitter_context_priv *ctx; 122 struct pipe_blend_state blend; 123 struct pipe_depth_stencil_alpha_state dsa; 124 struct pipe_rasterizer_state rs_state; 125 struct pipe_sampler_state *sampler_state; 126 struct pipe_vertex_element velem[2]; 127 unsigned i; 128 129 ctx = CALLOC_STRUCT(blitter_context_priv); 130 if (!ctx) 131 return NULL; 132 133 ctx->base.pipe = pipe; 134 ctx->base.draw_rectangle = blitter_draw_rectangle; 135 136 /* init state objects for them to be considered invalid */ 137 ctx->base.saved_blend_state = INVALID_PTR; 138 ctx->base.saved_dsa_state = INVALID_PTR; 139 ctx->base.saved_rs_state = INVALID_PTR; 140 ctx->base.saved_fs = INVALID_PTR; 141 ctx->base.saved_vs = INVALID_PTR; 142 ctx->base.saved_velem_state = INVALID_PTR; 143 ctx->base.saved_fb_state.nr_cbufs = ~0; 144 ctx->base.saved_num_sampler_views = ~0; 145 ctx->base.saved_num_sampler_states = ~0; 146 ctx->base.saved_num_vertex_buffers = ~0; 147 148 /* blend state objects */ 149 memset(&blend, 0, sizeof(blend)); 150 ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend); 151 152 blend.rt[0].colormask = PIPE_MASK_RGBA; 153 ctx->blend_write_color = pipe->create_blend_state(pipe, &blend); 154 155 /* depth stencil alpha state objects */ 156 memset(&dsa, 0, sizeof(dsa)); 157 ctx->dsa_keep_depth_stencil = 158 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 159 160 dsa.depth.enabled = 1; 161 dsa.depth.writemask = 1; 162 dsa.depth.func = PIPE_FUNC_ALWAYS; 163 ctx->dsa_write_depth_keep_stencil = 164 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 165 166 dsa.stencil[0].enabled = 1; 167 dsa.stencil[0].func = PIPE_FUNC_ALWAYS; 168 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; 169 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; 170 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; 171 dsa.stencil[0].valuemask = 0xff; 172 dsa.stencil[0].writemask = 0xff; 173 ctx->dsa_write_depth_stencil = 174 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 175 176 177 dsa.depth.enabled = 0; 178 dsa.depth.writemask = 0; 179 ctx->dsa_keep_depth_write_stencil = 180 pipe->create_depth_stencil_alpha_state(pipe, &dsa); 181 182 /* sampler state */ 183 sampler_state = &ctx->template_sampler_state; 184 sampler_state->wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 185 sampler_state->wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 186 sampler_state->wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 187 sampler_state->normalized_coords = TRUE; 188 /* The sampler state objects which sample from a specified mipmap level 189 * are created on-demand. */ 190 191 /* rasterizer state */ 192 memset(&rs_state, 0, sizeof(rs_state)); 193 rs_state.cull_face = PIPE_FACE_NONE; 194 rs_state.gl_rasterization_rules = 1; 195 rs_state.flatshade = 1; 196 ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); 197 198 /* vertex elements state */ 199 memset(&velem[0], 0, sizeof(velem[0]) * 2); 200 for (i = 0; i < 2; i++) { 201 velem[i].src_offset = i * 4 * sizeof(float); 202 velem[i].instance_divisor = 0; 203 velem[i].vertex_buffer_index = 0; 204 velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 205 } 206 ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]); 207 208 /* fragment shaders are created on-demand */ 209 210 /* vertex shader */ 211 { 212 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, 213 TGSI_SEMANTIC_GENERIC }; 214 const uint semantic_indices[] = { 0, 0 }; 215 ctx->vs = 216 util_make_vertex_passthrough_shader(pipe, 2, semantic_names, 217 semantic_indices); 218 } 219 220 /* set invariant vertex coordinates */ 221 for (i = 0; i < 4; i++) 222 ctx->vertices[i][0][3] = 1; /*v.w*/ 223 224 /* create the vertex buffer */ 225 ctx->vbuf = pipe_user_buffer_create(ctx->base.pipe->screen, 226 ctx->vertices, 227 sizeof(ctx->vertices), 228 PIPE_BIND_VERTEX_BUFFER); 229 230 return &ctx->base; 231} 232 233void util_blitter_destroy(struct blitter_context *blitter) 234{ 235 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 236 struct pipe_context *pipe = blitter->pipe; 237 int i; 238 239 pipe->delete_blend_state(pipe, ctx->blend_write_color); 240 pipe->delete_blend_state(pipe, ctx->blend_keep_color); 241 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 242 pipe->delete_depth_stencil_alpha_state(pipe, 243 ctx->dsa_write_depth_keep_stencil); 244 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); 245 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); 246 247 pipe->delete_rasterizer_state(pipe, ctx->rs_state); 248 pipe->delete_vs_state(pipe, ctx->vs); 249 pipe->delete_vertex_elements_state(pipe, ctx->velem_state); 250 251 for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { 252 if (ctx->fs_texfetch_col[i]) 253 pipe->delete_fs_state(pipe, ctx->fs_texfetch_col[i]); 254 if (ctx->fs_texfetch_depth[i]) 255 pipe->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]); 256 } 257 258 for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++) 259 if (ctx->fs_col[i]) 260 pipe->delete_fs_state(pipe, ctx->fs_col[i]); 261 262 for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS * 2; i++) 263 if (ctx->sampler_state[i]) 264 pipe->delete_sampler_state(pipe, ctx->sampler_state[i]); 265 266 pipe_resource_reference(&ctx->vbuf, NULL); 267 FREE(ctx); 268} 269 270static void blitter_check_saved_CSOs(struct blitter_context_priv *ctx) 271{ 272 if (ctx->running) { 273 _debug_printf("u_blitter: Caught recursion on save. " 274 "This is a driver bug.\n"); 275 } 276 ctx->running = TRUE; 277 278 /* make sure these CSOs have been saved */ 279 assert(ctx->base.saved_blend_state != INVALID_PTR && 280 ctx->base.saved_dsa_state != INVALID_PTR && 281 ctx->base.saved_rs_state != INVALID_PTR && 282 ctx->base.saved_fs != INVALID_PTR && 283 ctx->base.saved_vs != INVALID_PTR && 284 ctx->base.saved_velem_state != INVALID_PTR); 285} 286 287static void blitter_restore_CSOs(struct blitter_context_priv *ctx) 288{ 289 struct pipe_context *pipe = ctx->base.pipe; 290 unsigned i; 291 292 /* restore the state objects which are always required to be saved */ 293 pipe->bind_blend_state(pipe, ctx->base.saved_blend_state); 294 pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state); 295 pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state); 296 pipe->bind_fs_state(pipe, ctx->base.saved_fs); 297 pipe->bind_vs_state(pipe, ctx->base.saved_vs); 298 pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state); 299 300 ctx->base.saved_blend_state = INVALID_PTR; 301 ctx->base.saved_dsa_state = INVALID_PTR; 302 ctx->base.saved_rs_state = INVALID_PTR; 303 ctx->base.saved_fs = INVALID_PTR; 304 ctx->base.saved_vs = INVALID_PTR; 305 ctx->base.saved_velem_state = INVALID_PTR; 306 307 pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref); 308 pipe->set_viewport_state(pipe, &ctx->base.saved_viewport); 309 pipe->set_clip_state(pipe, &ctx->base.saved_clip); 310 311 /* restore the state objects which are required to be saved before copy/fill 312 */ 313 if (ctx->base.saved_fb_state.nr_cbufs != ~0) { 314 pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state); 315 util_unreference_framebuffer_state(&ctx->base.saved_fb_state); 316 ctx->base.saved_fb_state.nr_cbufs = ~0; 317 } 318 319 if (ctx->base.saved_num_sampler_states != ~0) { 320 pipe->bind_fragment_sampler_states(pipe, 321 ctx->base.saved_num_sampler_states, 322 ctx->base.saved_sampler_states); 323 ctx->base.saved_num_sampler_states = ~0; 324 } 325 326 if (ctx->base.saved_num_sampler_views != ~0) { 327 pipe->set_fragment_sampler_views(pipe, 328 ctx->base.saved_num_sampler_views, 329 ctx->base.saved_sampler_views); 330 331 for (i = 0; i < ctx->base.saved_num_sampler_views; i++) 332 pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i], 333 NULL); 334 335 ctx->base.saved_num_sampler_views = ~0; 336 } 337 338 if (ctx->base.saved_num_vertex_buffers != ~0) { 339 pipe->set_vertex_buffers(pipe, 340 ctx->base.saved_num_vertex_buffers, 341 ctx->base.saved_vertex_buffers); 342 343 for (i = 0; i < ctx->base.saved_num_vertex_buffers; i++) { 344 if (ctx->base.saved_vertex_buffers[i].buffer) { 345 pipe_resource_reference(&ctx->base.saved_vertex_buffers[i].buffer, 346 NULL); 347 } 348 } 349 ctx->base.saved_num_vertex_buffers = ~0; 350 } 351 352 if (!ctx->running) { 353 _debug_printf("u_blitter: Caught recursion on restore. " 354 "This is a driver bug.\n"); 355 } 356 ctx->running = FALSE; 357} 358 359static void blitter_set_rectangle(struct blitter_context_priv *ctx, 360 unsigned x1, unsigned y1, 361 unsigned x2, unsigned y2, 362 float depth) 363{ 364 int i; 365 366 /* set vertex positions */ 367 ctx->vertices[0][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v0.x*/ 368 ctx->vertices[0][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v0.y*/ 369 370 ctx->vertices[1][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v1.x*/ 371 ctx->vertices[1][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v1.y*/ 372 373 ctx->vertices[2][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v2.x*/ 374 ctx->vertices[2][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v2.y*/ 375 376 ctx->vertices[3][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v3.x*/ 377 ctx->vertices[3][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v3.y*/ 378 379 for (i = 0; i < 4; i++) 380 ctx->vertices[i][0][2] = depth; /*z*/ 381 382 /* viewport */ 383 ctx->viewport.scale[0] = 0.5f * ctx->dst_width; 384 ctx->viewport.scale[1] = 0.5f * ctx->dst_height; 385 ctx->viewport.scale[2] = 1.0f; 386 ctx->viewport.scale[3] = 1.0f; 387 ctx->viewport.translate[0] = 0.5f * ctx->dst_width; 388 ctx->viewport.translate[1] = 0.5f * ctx->dst_height; 389 ctx->viewport.translate[2] = 0.0f; 390 ctx->viewport.translate[3] = 0.0f; 391 ctx->base.pipe->set_viewport_state(ctx->base.pipe, &ctx->viewport); 392 393 /* clip */ 394 ctx->base.pipe->set_clip_state(ctx->base.pipe, &ctx->clip); 395} 396 397static void blitter_set_clear_color(struct blitter_context_priv *ctx, 398 const float *rgba) 399{ 400 int i; 401 402 if (rgba) { 403 for (i = 0; i < 4; i++) { 404 ctx->vertices[i][1][0] = rgba[0]; 405 ctx->vertices[i][1][1] = rgba[1]; 406 ctx->vertices[i][1][2] = rgba[2]; 407 ctx->vertices[i][1][3] = rgba[3]; 408 } 409 } else { 410 for (i = 0; i < 4; i++) { 411 ctx->vertices[i][1][0] = 0; 412 ctx->vertices[i][1][1] = 0; 413 ctx->vertices[i][1][2] = 0; 414 ctx->vertices[i][1][3] = 0; 415 } 416 } 417} 418 419static void get_texcoords(struct pipe_resource *src, 420 unsigned level, 421 unsigned x1, unsigned y1, 422 unsigned x2, unsigned y2, 423 boolean normalized, float out[4]) 424{ 425 if(normalized) 426 { 427 out[0] = x1 / (float)u_minify(src->width0, level); 428 out[1] = y1 / (float)u_minify(src->height0, level); 429 out[2] = x2 / (float)u_minify(src->width0, level); 430 out[3] = y2 / (float)u_minify(src->height0, level); 431 } 432 else 433 { 434 out[0] = x1; 435 out[1] = y1; 436 out[2] = x2; 437 out[3] = y2; 438 } 439} 440 441static void set_texcoords_in_vertices(const float coord[4], 442 float *out, unsigned stride) 443{ 444 out[0] = coord[0]; /*t0.s*/ 445 out[1] = coord[1]; /*t0.t*/ 446 out += stride; 447 out[0] = coord[2]; /*t1.s*/ 448 out[1] = coord[1]; /*t1.t*/ 449 out += stride; 450 out[0] = coord[2]; /*t2.s*/ 451 out[1] = coord[3]; /*t2.t*/ 452 out += stride; 453 out[0] = coord[0]; /*t3.s*/ 454 out[1] = coord[3]; /*t3.t*/ 455} 456 457static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx, 458 struct pipe_resource *src, 459 unsigned level, 460 unsigned x1, unsigned y1, 461 unsigned x2, unsigned y2) 462{ 463 unsigned i; 464 float coord[4]; 465 466 get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord); 467 set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8); 468 469 for (i = 0; i < 4; i++) { 470 ctx->vertices[i][1][2] = 0; /*r*/ 471 ctx->vertices[i][1][3] = 1; /*q*/ 472 } 473} 474 475static void blitter_set_texcoords_3d(struct blitter_context_priv *ctx, 476 struct pipe_resource *src, 477 unsigned level, 478 unsigned zslice, 479 unsigned x1, unsigned y1, 480 unsigned x2, unsigned y2) 481{ 482 int i; 483 float r = zslice / (float)u_minify(src->depth0, level); 484 485 blitter_set_texcoords_2d(ctx, src, level, x1, y1, x2, y2); 486 487 for (i = 0; i < 4; i++) 488 ctx->vertices[i][1][2] = r; /*r*/ 489} 490 491static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx, 492 struct pipe_resource *src, 493 unsigned level, unsigned face, 494 unsigned x1, unsigned y1, 495 unsigned x2, unsigned y2) 496{ 497 int i; 498 float coord[4]; 499 float st[4][2]; 500 501 get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord); 502 set_texcoords_in_vertices(coord, &st[0][0], 2); 503 504 util_map_texcoords2d_onto_cubemap(face, 505 /* pointer, stride in floats */ 506 &st[0][0], 2, 507 &ctx->vertices[0][1][0], 8); 508 509 for (i = 0; i < 4; i++) 510 ctx->vertices[i][1][3] = 1; /*q*/ 511} 512 513static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx, 514 unsigned width, unsigned height) 515{ 516 ctx->dst_width = width; 517 ctx->dst_height = height; 518} 519 520static INLINE 521void **blitter_get_sampler_state(struct blitter_context_priv *ctx, 522 int miplevel, boolean normalized) 523{ 524 struct pipe_context *pipe = ctx->base.pipe; 525 struct pipe_sampler_state *sampler_state = &ctx->template_sampler_state; 526 527 assert(miplevel < PIPE_MAX_TEXTURE_LEVELS); 528 529 /* Create the sampler state on-demand. */ 530 if (!ctx->sampler_state[miplevel * 2 + normalized]) { 531 sampler_state->lod_bias = miplevel; 532 sampler_state->min_lod = miplevel; 533 sampler_state->max_lod = miplevel; 534 sampler_state->normalized_coords = normalized; 535 536 ctx->sampler_state[miplevel * 2 + normalized] = pipe->create_sampler_state(pipe, 537 sampler_state); 538 } 539 540 /* Return void** so that it can be passed to bind_fragment_sampler_states 541 * directly. */ 542 return &ctx->sampler_state[miplevel * 2 + normalized]; 543} 544 545static INLINE 546void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs) 547{ 548 struct pipe_context *pipe = ctx->base.pipe; 549 550 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); 551 552 if (!ctx->fs_col[num_cbufs]) 553 ctx->fs_col[num_cbufs] = 554 util_make_fragment_cloneinput_shader(pipe, num_cbufs, 555 TGSI_SEMANTIC_GENERIC, 556 TGSI_INTERPOLATE_LINEAR); 557 558 return ctx->fs_col[num_cbufs]; 559} 560 561/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */ 562static unsigned 563pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target) 564{ 565 switch (pipe_tex_target) { 566 case PIPE_TEXTURE_1D: 567 return TGSI_TEXTURE_1D; 568 case PIPE_TEXTURE_2D: 569 return TGSI_TEXTURE_2D; 570 case PIPE_TEXTURE_RECT: 571 return TGSI_TEXTURE_RECT; 572 case PIPE_TEXTURE_3D: 573 return TGSI_TEXTURE_3D; 574 case PIPE_TEXTURE_CUBE: 575 return TGSI_TEXTURE_CUBE; 576 default: 577 assert(0 && "unexpected texture target"); 578 return TGSI_TEXTURE_UNKNOWN; 579 } 580} 581 582 583static INLINE 584void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, 585 unsigned tex_target) 586{ 587 struct pipe_context *pipe = ctx->base.pipe; 588 589 assert(tex_target < PIPE_MAX_TEXTURE_TYPES); 590 591 /* Create the fragment shader on-demand. */ 592 if (!ctx->fs_texfetch_col[tex_target]) { 593 unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target); 594 595 ctx->fs_texfetch_col[tex_target] = 596 util_make_fragment_tex_shader(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR); 597 } 598 599 return ctx->fs_texfetch_col[tex_target]; 600} 601 602static INLINE 603void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx, 604 unsigned tex_target) 605{ 606 struct pipe_context *pipe = ctx->base.pipe; 607 608 assert(tex_target < PIPE_MAX_TEXTURE_TYPES); 609 610 /* Create the fragment shader on-demand. */ 611 if (!ctx->fs_texfetch_depth[tex_target]) { 612 unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target); 613 614 ctx->fs_texfetch_depth[tex_target] = 615 util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex, 616 TGSI_INTERPOLATE_LINEAR); 617 } 618 619 return ctx->fs_texfetch_depth[tex_target]; 620} 621 622static void blitter_draw_rectangle(struct blitter_context *blitter, 623 unsigned x1, unsigned y1, 624 unsigned x2, unsigned y2, 625 float depth, 626 enum blitter_attrib_type type, 627 const float attrib[4]) 628{ 629 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 630 631 switch (type) { 632 case UTIL_BLITTER_ATTRIB_COLOR: 633 blitter_set_clear_color(ctx, attrib); 634 break; 635 636 case UTIL_BLITTER_ATTRIB_TEXCOORD: 637 set_texcoords_in_vertices(attrib, &ctx->vertices[0][1][0], 8); 638 break; 639 640 default:; 641 } 642 643 blitter_set_rectangle(ctx, x1, y1, x2, y2, depth); 644 util_draw_vertex_buffer(ctx->base.pipe, 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_region(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, 0) || 776 !screen->is_format_supported(screen, src->format, src->target, 777 src->nr_samples, PIPE_BIND_SAMPLER_VIEW, 0)) { 778 util_resource_copy_region(pipe, dst, dstlevel, dstx, dsty, dstz, 779 src, srclevel, srcbox); 780 return; 781 } 782 783 /* Get surface. */ 784 memset(&surf_templ, 0, sizeof(surf_templ)); 785 u_surface_default_template(&surf_templ, dst, bind); 786 surf_templ.u.tex.level = dstlevel; 787 surf_templ.u.tex.first_layer = dstz; 788 surf_templ.u.tex.last_layer = dstz; 789 dstsurf = pipe->create_surface(pipe, dst, &surf_templ); 790 791 /* Check whether the states are properly saved. */ 792 blitter_check_saved_CSOs(ctx); 793 assert(blitter->saved_fb_state.nr_cbufs != ~0); 794 assert(blitter->saved_num_sampler_views != ~0); 795 assert(blitter->saved_num_sampler_states != ~0); 796 797 /* Initialize framebuffer state. */ 798 fb_state.width = dstsurf->width; 799 fb_state.height = dstsurf->height; 800 801 if (is_depth) { 802 pipe->bind_blend_state(pipe, ctx->blend_keep_color); 803 pipe->bind_depth_stencil_alpha_state(pipe, 804 ctx->dsa_write_depth_keep_stencil); 805 pipe->bind_fs_state(pipe, 806 blitter_get_fs_texfetch_depth(ctx, src->target)); 807 808 fb_state.nr_cbufs = 0; 809 fb_state.zsbuf = dstsurf; 810 } else { 811 pipe->bind_blend_state(pipe, ctx->blend_write_color); 812 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 813 pipe->bind_fs_state(pipe, 814 blitter_get_fs_texfetch_col(ctx, src->target)); 815 816 fb_state.nr_cbufs = 1; 817 fb_state.cbufs[0] = dstsurf; 818 fb_state.zsbuf = 0; 819 } 820 821 normalized = src->target != PIPE_TEXTURE_RECT; 822 823 /* Initialize sampler view. */ 824 u_sampler_view_default_template(&viewTempl, src, src->format); 825 view = pipe->create_sampler_view(pipe, src, &viewTempl); 826 827 /* Set rasterizer state, shaders, and textures. */ 828 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 829 pipe->bind_vs_state(pipe, ctx->vs); 830 pipe->bind_fragment_sampler_states(pipe, 1, 831 blitter_get_sampler_state(ctx, srclevel, normalized)); 832 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 833 pipe->set_fragment_sampler_views(pipe, 1, &view); 834 pipe->set_framebuffer_state(pipe, &fb_state); 835 836 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); 837 838 switch (src->target) { 839 /* Draw the quad with the draw_rectangle callback. */ 840 case PIPE_TEXTURE_1D: 841 case PIPE_TEXTURE_2D: 842 case PIPE_TEXTURE_RECT: 843 { 844 /* Set texture coordinates. */ 845 float coord[4]; 846 get_texcoords(src, srclevel, srcbox->x, srcbox->y, 847 srcbox->x+width, srcbox->y+height, normalized, coord); 848 849 /* Draw. */ 850 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, 851 UTIL_BLITTER_ATTRIB_TEXCOORD, coord); 852 } 853 break; 854 855 /* Draw the quad with the generic codepath. */ 856 case PIPE_TEXTURE_3D: 857 case PIPE_TEXTURE_CUBE: 858 /* Set texture coordinates. */ 859 if (src->target == PIPE_TEXTURE_3D) 860 blitter_set_texcoords_3d(ctx, src, srclevel, srcbox->z, 861 srcbox->x, srcbox->y, 862 srcbox->x + width, srcbox->y + height); 863 else 864 blitter_set_texcoords_cube(ctx, src, srclevel, srcbox->z, 865 srcbox->x, srcbox->y, 866 srcbox->x + width, srcbox->y + height); 867 868 /* Draw. */ 869 blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0); 870 util_draw_vertex_buffer(ctx->base.pipe, ctx->vbuf, 0, 871 PIPE_PRIM_TRIANGLE_FAN, 4, 2); 872 break; 873 874 default: 875 assert(0); 876 return; 877 } 878 879 blitter_restore_CSOs(ctx); 880 881 pipe_surface_reference(&dstsurf, NULL); 882 pipe_sampler_view_reference(&view, NULL); 883} 884 885/* Clear a region of a color surface to a constant value. */ 886void util_blitter_clear_render_target(struct blitter_context *blitter, 887 struct pipe_surface *dstsurf, 888 const float *rgba, 889 unsigned dstx, unsigned dsty, 890 unsigned width, unsigned height) 891{ 892 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 893 struct pipe_context *pipe = ctx->base.pipe; 894 struct pipe_framebuffer_state fb_state; 895 896 assert(dstsurf->texture); 897 if (!dstsurf->texture) 898 return; 899 900 /* check the saved state */ 901 blitter_check_saved_CSOs(ctx); 902 assert(blitter->saved_fb_state.nr_cbufs != ~0); 903 904 /* bind CSOs */ 905 pipe->bind_blend_state(pipe, ctx->blend_write_color); 906 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 907 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 908 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1)); 909 pipe->bind_vs_state(pipe, ctx->vs); 910 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 911 912 /* set a framebuffer state */ 913 fb_state.width = dstsurf->width; 914 fb_state.height = dstsurf->height; 915 fb_state.nr_cbufs = 1; 916 fb_state.cbufs[0] = dstsurf; 917 fb_state.zsbuf = 0; 918 pipe->set_framebuffer_state(pipe, &fb_state); 919 920 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); 921 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, 922 UTIL_BLITTER_ATTRIB_COLOR, rgba); 923 blitter_restore_CSOs(ctx); 924} 925 926/* Clear a region of a depth stencil surface. */ 927void util_blitter_clear_depth_stencil(struct blitter_context *blitter, 928 struct pipe_surface *dstsurf, 929 unsigned clear_flags, 930 double depth, 931 unsigned stencil, 932 unsigned dstx, unsigned dsty, 933 unsigned width, unsigned height) 934{ 935 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 936 struct pipe_context *pipe = ctx->base.pipe; 937 struct pipe_framebuffer_state fb_state; 938 struct pipe_stencil_ref sr = { { 0 } }; 939 940 assert(dstsurf->texture); 941 if (!dstsurf->texture) 942 return; 943 944 /* check the saved state */ 945 blitter_check_saved_CSOs(ctx); 946 assert(blitter->saved_fb_state.nr_cbufs != ~0); 947 948 /* bind CSOs */ 949 pipe->bind_blend_state(pipe, ctx->blend_keep_color); 950 if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { 951 sr.ref_value[0] = stencil & 0xff; 952 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); 953 pipe->set_stencil_ref(pipe, &sr); 954 } 955 else if (clear_flags & PIPE_CLEAR_DEPTH) { 956 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); 957 } 958 else if (clear_flags & PIPE_CLEAR_STENCIL) { 959 sr.ref_value[0] = stencil & 0xff; 960 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); 961 pipe->set_stencil_ref(pipe, &sr); 962 } 963 else 964 /* hmm that should be illegal probably, or make it a no-op somewhere */ 965 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); 966 967 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 968 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0)); 969 pipe->bind_vs_state(pipe, ctx->vs); 970 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 971 972 /* set a framebuffer state */ 973 fb_state.width = dstsurf->width; 974 fb_state.height = dstsurf->height; 975 fb_state.nr_cbufs = 0; 976 fb_state.cbufs[0] = 0; 977 fb_state.zsbuf = dstsurf; 978 pipe->set_framebuffer_state(pipe, &fb_state); 979 980 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); 981 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, depth, 982 UTIL_BLITTER_ATTRIB_NONE, NULL); 983 blitter_restore_CSOs(ctx); 984} 985 986/* draw a rectangle across a region using a custom dsa stage - for r600g */ 987void util_blitter_custom_depth_stencil(struct blitter_context *blitter, 988 struct pipe_surface *zsurf, 989 struct pipe_surface *cbsurf, 990 void *dsa_stage, float depth) 991{ 992 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; 993 struct pipe_context *pipe = ctx->base.pipe; 994 struct pipe_framebuffer_state fb_state; 995 996 assert(zsurf->texture); 997 if (!zsurf->texture) 998 return; 999 1000 /* check the saved state */ 1001 blitter_check_saved_CSOs(ctx); 1002 assert(blitter->saved_fb_state.nr_cbufs != ~0); 1003 1004 /* bind CSOs */ 1005 pipe->bind_blend_state(pipe, ctx->blend_write_color); 1006 pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage); 1007 1008 pipe->bind_rasterizer_state(pipe, ctx->rs_state); 1009 pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0)); 1010 pipe->bind_vs_state(pipe, ctx->vs); 1011 pipe->bind_vertex_elements_state(pipe, ctx->velem_state); 1012 1013 /* set a framebuffer state */ 1014 fb_state.width = zsurf->width; 1015 fb_state.height = zsurf->height; 1016 fb_state.nr_cbufs = 1; 1017 if (cbsurf) { 1018 fb_state.cbufs[0] = cbsurf; 1019 fb_state.nr_cbufs = 1; 1020 } else { 1021 fb_state.cbufs[0] = NULL; 1022 fb_state.nr_cbufs = 0; 1023 } 1024 fb_state.zsbuf = zsurf; 1025 pipe->set_framebuffer_state(pipe, &fb_state); 1026 1027 blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height); 1028 blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth, 1029 UTIL_BLITTER_ATTRIB_NONE, NULL); 1030 blitter_restore_CSOs(ctx); 1031} 1032