u_blitter: add cube map array support.
[mesa.git] / src / gallium / auxiliary / util / u_blitter.c
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, resource_copy_region, and blit 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 #include "util/u_upload_mgr.h"
51
52 #define INVALID_PTR ((void*)~0)
53
54 struct blitter_context_priv
55 {
56 struct blitter_context base;
57
58 struct u_upload_mgr *upload;
59
60 float vertices[4][2][4]; /**< {pos, color} or {pos, texcoord} */
61
62 /* Templates for various state objects. */
63
64 /* Constant state objects. */
65 /* Vertex shaders. */
66 void *vs; /**< Vertex shader which passes {pos, generic} to the output.*/
67 void *vs_pos_only; /**< Vertex shader which passes pos to the output.*/
68
69 /* Fragment shaders. */
70 /* The shader at index i outputs color to color buffers 0,1,...,i-1. */
71 void *fs_col[PIPE_MAX_COLOR_BUFS+1];
72 void *fs_col_int[PIPE_MAX_COLOR_BUFS+1];
73
74 /* FS which outputs a color from a texture,
75 where the index is PIPE_TEXTURE_* to be sampled. */
76 void *fs_texfetch_col[PIPE_MAX_TEXTURE_TYPES];
77
78 /* FS which outputs a depth from a texture,
79 where the index is PIPE_TEXTURE_* to be sampled. */
80 void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES];
81 void *fs_texfetch_depthstencil[PIPE_MAX_TEXTURE_TYPES];
82 void *fs_texfetch_stencil[PIPE_MAX_TEXTURE_TYPES];
83
84 /* FS which outputs one sample from a multisample texture. */
85 void *fs_texfetch_col_msaa[PIPE_MAX_TEXTURE_TYPES];
86 void *fs_texfetch_depth_msaa[PIPE_MAX_TEXTURE_TYPES];
87 void *fs_texfetch_depthstencil_msaa[PIPE_MAX_TEXTURE_TYPES];
88 void *fs_texfetch_stencil_msaa[PIPE_MAX_TEXTURE_TYPES];
89
90 /* Blend state. */
91 void *blend[PIPE_MASK_RGBA+1]; /**< blend state with writemask */
92
93 /* Depth stencil alpha state. */
94 void *dsa_write_depth_stencil;
95 void *dsa_write_depth_keep_stencil;
96 void *dsa_keep_depth_stencil;
97 void *dsa_keep_depth_write_stencil;
98
99 /* Vertex elements states. */
100 void *velem_state;
101 void *velem_uint_state;
102 void *velem_sint_state;
103 void *velem_state_readbuf;
104
105 /* Sampler state. */
106 void *sampler_state, *sampler_state_linear;
107
108 /* Rasterizer state. */
109 void *rs_state, *rs_state_scissor, *rs_discard_state;
110
111 /* Viewport state. */
112 struct pipe_viewport_state viewport;
113
114 /* Destination surface dimensions. */
115 unsigned dst_width;
116 unsigned dst_height;
117
118 boolean has_geometry_shader;
119 boolean vertex_has_integers;
120 boolean has_stream_out;
121 boolean has_stencil_export;
122 boolean has_texture_multisample;
123
124 /* The Draw module overrides these functions.
125 * Always create the blitter before Draw. */
126 void (*bind_fs_state)(struct pipe_context *, void *);
127 void (*delete_fs_state)(struct pipe_context *, void *);
128 };
129
130 struct blitter_context *util_blitter_create(struct pipe_context *pipe)
131 {
132 struct blitter_context_priv *ctx;
133 struct pipe_blend_state blend;
134 struct pipe_depth_stencil_alpha_state dsa;
135 struct pipe_rasterizer_state rs_state;
136 struct pipe_sampler_state sampler_state;
137 struct pipe_vertex_element velem[2];
138 unsigned i;
139
140 ctx = CALLOC_STRUCT(blitter_context_priv);
141 if (!ctx)
142 return NULL;
143
144 ctx->base.pipe = pipe;
145 ctx->base.draw_rectangle = util_blitter_draw_rectangle;
146
147 ctx->bind_fs_state = pipe->bind_fs_state;
148 ctx->delete_fs_state = pipe->delete_fs_state;
149
150 /* init state objects for them to be considered invalid */
151 ctx->base.saved_blend_state = INVALID_PTR;
152 ctx->base.saved_dsa_state = INVALID_PTR;
153 ctx->base.saved_rs_state = INVALID_PTR;
154 ctx->base.saved_fs = INVALID_PTR;
155 ctx->base.saved_vs = INVALID_PTR;
156 ctx->base.saved_gs = INVALID_PTR;
157 ctx->base.saved_velem_state = INVALID_PTR;
158 ctx->base.saved_fb_state.nr_cbufs = ~0;
159 ctx->base.saved_num_sampler_views = ~0;
160 ctx->base.saved_num_sampler_states = ~0;
161 ctx->base.saved_num_so_targets = ~0;
162
163 ctx->has_geometry_shader =
164 pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY,
165 PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
166 ctx->vertex_has_integers =
167 pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_VERTEX,
168 PIPE_SHADER_CAP_INTEGERS);
169 ctx->has_stream_out =
170 pipe->screen->get_param(pipe->screen,
171 PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0;
172
173 ctx->has_stencil_export =
174 pipe->screen->get_param(pipe->screen,
175 PIPE_CAP_SHADER_STENCIL_EXPORT);
176
177 ctx->has_texture_multisample =
178 pipe->screen->get_param(pipe->screen, PIPE_CAP_TEXTURE_MULTISAMPLE);
179
180 /* blend state objects */
181 memset(&blend, 0, sizeof(blend));
182
183 for (i = 0; i <= PIPE_MASK_RGBA; i++) {
184 blend.rt[0].colormask = i;
185 ctx->blend[i] = pipe->create_blend_state(pipe, &blend);
186 }
187
188 /* depth stencil alpha state objects */
189 memset(&dsa, 0, sizeof(dsa));
190 ctx->dsa_keep_depth_stencil =
191 pipe->create_depth_stencil_alpha_state(pipe, &dsa);
192
193 dsa.depth.enabled = 1;
194 dsa.depth.writemask = 1;
195 dsa.depth.func = PIPE_FUNC_ALWAYS;
196 ctx->dsa_write_depth_keep_stencil =
197 pipe->create_depth_stencil_alpha_state(pipe, &dsa);
198
199 dsa.stencil[0].enabled = 1;
200 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
201 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
202 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
203 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
204 dsa.stencil[0].valuemask = 0xff;
205 dsa.stencil[0].writemask = 0xff;
206 ctx->dsa_write_depth_stencil =
207 pipe->create_depth_stencil_alpha_state(pipe, &dsa);
208
209 dsa.depth.enabled = 0;
210 dsa.depth.writemask = 0;
211 ctx->dsa_keep_depth_write_stencil =
212 pipe->create_depth_stencil_alpha_state(pipe, &dsa);
213
214 /* sampler state */
215 memset(&sampler_state, 0, sizeof(sampler_state));
216 sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
217 sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
218 sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
219 sampler_state.normalized_coords = 1;
220 ctx->sampler_state = pipe->create_sampler_state(pipe, &sampler_state);
221
222 sampler_state.min_img_filter = PIPE_TEX_FILTER_LINEAR;
223 sampler_state.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
224 ctx->sampler_state_linear = pipe->create_sampler_state(pipe, &sampler_state);
225
226 /* rasterizer state */
227 memset(&rs_state, 0, sizeof(rs_state));
228 rs_state.cull_face = PIPE_FACE_NONE;
229 rs_state.gl_rasterization_rules = 1;
230 rs_state.flatshade = 1;
231 rs_state.depth_clip = 1;
232 ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state);
233
234 rs_state.scissor = 1;
235 ctx->rs_state_scissor = pipe->create_rasterizer_state(pipe, &rs_state);
236
237 if (ctx->has_stream_out) {
238 rs_state.scissor = 0;
239 rs_state.rasterizer_discard = 1;
240 ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state);
241 }
242
243 ctx->base.vb_slot = 0; /* 0 for now */
244
245 /* vertex elements states */
246 memset(&velem[0], 0, sizeof(velem[0]) * 2);
247 for (i = 0; i < 2; i++) {
248 velem[i].src_offset = i * 4 * sizeof(float);
249 velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
250 velem[i].vertex_buffer_index = ctx->base.vb_slot;
251 }
252 ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
253
254 if (ctx->vertex_has_integers) {
255 memset(&velem[0], 0, sizeof(velem[0]) * 2);
256 velem[0].src_offset = 0;
257 velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
258 velem[0].vertex_buffer_index = ctx->base.vb_slot;
259 velem[1].src_offset = 4 * sizeof(float);
260 velem[1].src_format = PIPE_FORMAT_R32G32B32A32_SINT;
261 velem[1].vertex_buffer_index = ctx->base.vb_slot;
262 ctx->velem_sint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
263
264 memset(&velem[0], 0, sizeof(velem[0]) * 2);
265 velem[0].src_offset = 0;
266 velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
267 velem[0].vertex_buffer_index = ctx->base.vb_slot;
268 velem[1].src_offset = 4 * sizeof(float);
269 velem[1].src_format = PIPE_FORMAT_R32G32B32A32_UINT;
270 velem[1].vertex_buffer_index = ctx->base.vb_slot;
271 ctx->velem_uint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
272 }
273
274 if (ctx->has_stream_out) {
275 velem[0].src_format = PIPE_FORMAT_R32_UINT;
276 velem[0].vertex_buffer_index = ctx->base.vb_slot;
277 ctx->velem_state_readbuf = pipe->create_vertex_elements_state(pipe, 1, &velem[0]);
278 }
279
280 /* fragment shaders are created on-demand */
281
282 /* vertex shaders */
283 {
284 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
285 TGSI_SEMANTIC_GENERIC };
286 const uint semantic_indices[] = { 0, 0 };
287 ctx->vs =
288 util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
289 semantic_indices);
290 }
291 if (ctx->has_stream_out) {
292 struct pipe_stream_output_info so;
293 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION };
294 const uint semantic_indices[] = { 0 };
295
296 memset(&so, 0, sizeof(so));
297 so.num_outputs = 1;
298 so.output[0].num_components = 1;
299 so.stride[0] = 1;
300
301 ctx->vs_pos_only =
302 util_make_vertex_passthrough_shader_with_so(pipe, 1, semantic_names,
303 semantic_indices, &so);
304 }
305
306 /* set invariant vertex coordinates */
307 for (i = 0; i < 4; i++)
308 ctx->vertices[i][0][3] = 1; /*v.w*/
309
310 ctx->upload = u_upload_create(pipe, 65536, 4, PIPE_BIND_VERTEX_BUFFER);
311
312 return &ctx->base;
313 }
314
315 void util_blitter_destroy(struct blitter_context *blitter)
316 {
317 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
318 struct pipe_context *pipe = blitter->pipe;
319 int i;
320
321 for (i = 0; i <= PIPE_MASK_RGBA; i++) {
322 pipe->delete_blend_state(pipe, ctx->blend[i]);
323 }
324 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
325 pipe->delete_depth_stencil_alpha_state(pipe,
326 ctx->dsa_write_depth_keep_stencil);
327 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
328 pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
329
330 pipe->delete_rasterizer_state(pipe, ctx->rs_state);
331 pipe->delete_rasterizer_state(pipe, ctx->rs_state_scissor);
332 if (ctx->rs_discard_state)
333 pipe->delete_rasterizer_state(pipe, ctx->rs_discard_state);
334 pipe->delete_vs_state(pipe, ctx->vs);
335 if (ctx->vs_pos_only)
336 pipe->delete_vs_state(pipe, ctx->vs_pos_only);
337 pipe->delete_vertex_elements_state(pipe, ctx->velem_state);
338 if (ctx->vertex_has_integers) {
339 pipe->delete_vertex_elements_state(pipe, ctx->velem_sint_state);
340 pipe->delete_vertex_elements_state(pipe, ctx->velem_uint_state);
341 }
342 if (ctx->velem_state_readbuf)
343 pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf);
344
345 for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) {
346 if (ctx->fs_texfetch_col[i])
347 ctx->delete_fs_state(pipe, ctx->fs_texfetch_col[i]);
348 if (ctx->fs_texfetch_depth[i])
349 ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]);
350 if (ctx->fs_texfetch_depthstencil[i])
351 ctx->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil[i]);
352 if (ctx->fs_texfetch_stencil[i])
353 ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i]);
354 }
355
356 for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++) {
357 if (ctx->fs_col[i])
358 ctx->delete_fs_state(pipe, ctx->fs_col[i]);
359 if (ctx->fs_col_int[i])
360 ctx->delete_fs_state(pipe, ctx->fs_col_int[i]);
361 }
362
363 pipe->delete_sampler_state(pipe, ctx->sampler_state);
364 pipe->delete_sampler_state(pipe, ctx->sampler_state_linear);
365 u_upload_destroy(ctx->upload);
366 FREE(ctx);
367 }
368
369 void util_blitter_set_texture_multisample(struct blitter_context *blitter,
370 boolean supported)
371 {
372 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
373
374 ctx->has_texture_multisample = supported;
375 }
376
377 static void blitter_set_running_flag(struct blitter_context_priv *ctx)
378 {
379 if (ctx->base.running) {
380 _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
381 __LINE__);
382 }
383 ctx->base.running = TRUE;
384 }
385
386 static void blitter_unset_running_flag(struct blitter_context_priv *ctx)
387 {
388 if (!ctx->base.running) {
389 _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
390 __LINE__);
391 }
392 ctx->base.running = FALSE;
393 }
394
395 static void blitter_check_saved_vertex_states(struct blitter_context_priv *ctx)
396 {
397 assert(ctx->base.saved_velem_state != INVALID_PTR);
398 assert(ctx->base.saved_vs != INVALID_PTR);
399 assert(!ctx->has_geometry_shader || ctx->base.saved_gs != INVALID_PTR);
400 assert(!ctx->has_stream_out || ctx->base.saved_num_so_targets != ~0);
401 assert(ctx->base.saved_rs_state != INVALID_PTR);
402 }
403
404 static void blitter_restore_vertex_states(struct blitter_context_priv *ctx)
405 {
406 struct pipe_context *pipe = ctx->base.pipe;
407 unsigned i;
408
409 /* Vertex buffer. */
410 pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1,
411 &ctx->base.saved_vertex_buffer);
412 pipe_resource_reference(&ctx->base.saved_vertex_buffer.buffer, NULL);
413
414 /* Vertex elements. */
415 pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state);
416 ctx->base.saved_velem_state = INVALID_PTR;
417
418 /* Vertex shader. */
419 pipe->bind_vs_state(pipe, ctx->base.saved_vs);
420 ctx->base.saved_vs = INVALID_PTR;
421
422 /* Geometry shader. */
423 if (ctx->has_geometry_shader) {
424 pipe->bind_gs_state(pipe, ctx->base.saved_gs);
425 ctx->base.saved_gs = INVALID_PTR;
426 }
427
428 /* Stream outputs. */
429 if (ctx->has_stream_out) {
430 pipe->set_stream_output_targets(pipe,
431 ctx->base.saved_num_so_targets,
432 ctx->base.saved_so_targets, ~0);
433
434 for (i = 0; i < ctx->base.saved_num_so_targets; i++)
435 pipe_so_target_reference(&ctx->base.saved_so_targets[i], NULL);
436
437 ctx->base.saved_num_so_targets = ~0;
438 }
439
440 /* Rasterizer. */
441 pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state);
442 ctx->base.saved_rs_state = INVALID_PTR;
443 }
444
445 static void blitter_check_saved_fragment_states(struct blitter_context_priv *ctx)
446 {
447 assert(ctx->base.saved_fs != INVALID_PTR);
448 assert(ctx->base.saved_dsa_state != INVALID_PTR);
449 assert(ctx->base.saved_blend_state != INVALID_PTR);
450 }
451
452 static void blitter_restore_fragment_states(struct blitter_context_priv *ctx)
453 {
454 struct pipe_context *pipe = ctx->base.pipe;
455
456 /* Fragment shader. */
457 ctx->bind_fs_state(pipe, ctx->base.saved_fs);
458 ctx->base.saved_fs = INVALID_PTR;
459
460 /* Depth, stencil, alpha. */
461 pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state);
462 ctx->base.saved_dsa_state = INVALID_PTR;
463
464 /* Blend state. */
465 pipe->bind_blend_state(pipe, ctx->base.saved_blend_state);
466 ctx->base.saved_blend_state = INVALID_PTR;
467
468 /* Sample mask. */
469 if (ctx->base.is_sample_mask_saved) {
470 pipe->set_sample_mask(pipe, ctx->base.saved_sample_mask);
471 ctx->base.is_sample_mask_saved = FALSE;
472 }
473
474 /* Miscellaneous states. */
475 /* XXX check whether these are saved and whether they need to be restored
476 * (depending on the operation) */
477 pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref);
478 pipe->set_viewport_state(pipe, &ctx->base.saved_viewport);
479 }
480
481 static void blitter_check_saved_fb_state(struct blitter_context_priv *ctx)
482 {
483 assert(ctx->base.saved_fb_state.nr_cbufs != ~0);
484 }
485
486 static void blitter_disable_render_cond(struct blitter_context_priv *ctx)
487 {
488 struct pipe_context *pipe = ctx->base.pipe;
489
490 if (ctx->base.saved_render_cond_query) {
491 pipe->render_condition(pipe, NULL, 0);
492 }
493 }
494
495 static void blitter_restore_render_cond(struct blitter_context_priv *ctx)
496 {
497 struct pipe_context *pipe = ctx->base.pipe;
498
499 if (ctx->base.saved_render_cond_query) {
500 pipe->render_condition(pipe, ctx->base.saved_render_cond_query,
501 ctx->base.saved_render_cond_mode);
502 ctx->base.saved_render_cond_query = NULL;
503 }
504 }
505
506 static void blitter_restore_fb_state(struct blitter_context_priv *ctx)
507 {
508 struct pipe_context *pipe = ctx->base.pipe;
509
510 pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state);
511 util_unreference_framebuffer_state(&ctx->base.saved_fb_state);
512 }
513
514 static void blitter_check_saved_textures(struct blitter_context_priv *ctx)
515 {
516 assert(ctx->base.saved_num_sampler_states != ~0);
517 assert(ctx->base.saved_num_sampler_views != ~0);
518 }
519
520 static void blitter_restore_textures(struct blitter_context_priv *ctx)
521 {
522 struct pipe_context *pipe = ctx->base.pipe;
523 unsigned i;
524
525 /* Fragment sampler states. */
526 pipe->bind_fragment_sampler_states(pipe,
527 ctx->base.saved_num_sampler_states,
528 ctx->base.saved_sampler_states);
529 ctx->base.saved_num_sampler_states = ~0;
530
531 /* Fragment sampler views. */
532 pipe->set_fragment_sampler_views(pipe,
533 ctx->base.saved_num_sampler_views,
534 ctx->base.saved_sampler_views);
535
536 for (i = 0; i < ctx->base.saved_num_sampler_views; i++)
537 pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i], NULL);
538
539 ctx->base.saved_num_sampler_views = ~0;
540 }
541
542 static void blitter_set_rectangle(struct blitter_context_priv *ctx,
543 int x1, int y1, int x2, int y2,
544 float depth)
545 {
546 int i;
547
548 /* set vertex positions */
549 ctx->vertices[0][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v0.x*/
550 ctx->vertices[0][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v0.y*/
551
552 ctx->vertices[1][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v1.x*/
553 ctx->vertices[1][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v1.y*/
554
555 ctx->vertices[2][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v2.x*/
556 ctx->vertices[2][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v2.y*/
557
558 ctx->vertices[3][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v3.x*/
559 ctx->vertices[3][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v3.y*/
560
561 for (i = 0; i < 4; i++)
562 ctx->vertices[i][0][2] = depth; /*z*/
563
564 /* viewport */
565 ctx->viewport.scale[0] = 0.5f * ctx->dst_width;
566 ctx->viewport.scale[1] = 0.5f * ctx->dst_height;
567 ctx->viewport.scale[2] = 1.0f;
568 ctx->viewport.scale[3] = 1.0f;
569 ctx->viewport.translate[0] = 0.5f * ctx->dst_width;
570 ctx->viewport.translate[1] = 0.5f * ctx->dst_height;
571 ctx->viewport.translate[2] = 0.0f;
572 ctx->viewport.translate[3] = 0.0f;
573 ctx->base.pipe->set_viewport_state(ctx->base.pipe, &ctx->viewport);
574 }
575
576 static void blitter_set_clear_color(struct blitter_context_priv *ctx,
577 const union pipe_color_union *color)
578 {
579 int i;
580
581 if (color) {
582 for (i = 0; i < 4; i++) {
583 uint32_t *uiverts = (uint32_t *)ctx->vertices[i][1];
584 uiverts[0] = color->ui[0];
585 uiverts[1] = color->ui[1];
586 uiverts[2] = color->ui[2];
587 uiverts[3] = color->ui[3];
588 }
589 } else {
590 for (i = 0; i < 4; i++) {
591 ctx->vertices[i][1][0] = 0;
592 ctx->vertices[i][1][1] = 0;
593 ctx->vertices[i][1][2] = 0;
594 ctx->vertices[i][1][3] = 0;
595 }
596 }
597 }
598
599 static void get_texcoords(struct pipe_sampler_view *src,
600 unsigned src_width0, unsigned src_height0,
601 int x1, int y1, int x2, int y2,
602 float out[4])
603 {
604 struct pipe_resource *tex = src->texture;
605 unsigned level = src->u.tex.first_level;
606 boolean normalized = tex->target != PIPE_TEXTURE_RECT &&
607 tex->nr_samples <= 1;
608
609 if (normalized) {
610 out[0] = x1 / (float)u_minify(src_width0, level);
611 out[1] = y1 / (float)u_minify(src_height0, level);
612 out[2] = x2 / (float)u_minify(src_width0, level);
613 out[3] = y2 / (float)u_minify(src_height0, level);
614 } else {
615 out[0] = (float) x1;
616 out[1] = (float) y1;
617 out[2] = (float) x2;
618 out[3] = (float) y2;
619 }
620 }
621
622 static void set_texcoords_in_vertices(const float coord[4],
623 float *out, unsigned stride)
624 {
625 out[0] = coord[0]; /*t0.s*/
626 out[1] = coord[1]; /*t0.t*/
627 out += stride;
628 out[0] = coord[2]; /*t1.s*/
629 out[1] = coord[1]; /*t1.t*/
630 out += stride;
631 out[0] = coord[2]; /*t2.s*/
632 out[1] = coord[3]; /*t2.t*/
633 out += stride;
634 out[0] = coord[0]; /*t3.s*/
635 out[1] = coord[3]; /*t3.t*/
636 }
637
638 static void blitter_set_texcoords(struct blitter_context_priv *ctx,
639 struct pipe_sampler_view *src,
640 unsigned src_width0, unsigned src_height0,
641 unsigned layer, unsigned sample,
642 int x1, int y1, int x2, int y2)
643 {
644 unsigned i;
645 float coord[4];
646 float face_coord[4][2];
647
648 get_texcoords(src, src_width0, src_height0, x1, y1, x2, y2, coord);
649
650 if (src->texture->target == PIPE_TEXTURE_CUBE ||
651 src->texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
652 set_texcoords_in_vertices(coord, &face_coord[0][0], 2);
653 util_map_texcoords2d_onto_cubemap(layer % 6,
654 /* pointer, stride in floats */
655 &face_coord[0][0], 2,
656 &ctx->vertices[0][1][0], 8);
657 } else {
658 set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8);
659 }
660
661 /* Set the layer. */
662 switch (src->texture->target) {
663 case PIPE_TEXTURE_3D:
664 {
665 float r = layer / (float)u_minify(src->texture->depth0,
666 src->u.tex.first_level);
667 for (i = 0; i < 4; i++)
668 ctx->vertices[i][1][2] = r; /*r*/
669 }
670 break;
671
672 case PIPE_TEXTURE_1D_ARRAY:
673 for (i = 0; i < 4; i++)
674 ctx->vertices[i][1][1] = (float) layer; /*t*/
675 break;
676
677 case PIPE_TEXTURE_2D_ARRAY:
678 for (i = 0; i < 4; i++) {
679 ctx->vertices[i][1][2] = (float) layer; /*r*/
680 ctx->vertices[i][1][3] = (float) sample; /*q*/
681 }
682 break;
683
684 case PIPE_TEXTURE_2D:
685 for (i = 0; i < 4; i++) {
686 ctx->vertices[i][1][2] = (float) sample; /*r*/
687 }
688 break;
689
690 default:;
691 }
692 }
693
694 static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx,
695 unsigned width, unsigned height)
696 {
697 ctx->dst_width = width;
698 ctx->dst_height = height;
699 }
700
701 static void *blitter_get_fs_col(struct blitter_context_priv *ctx,
702 unsigned num_cbufs, boolean int_format)
703 {
704 struct pipe_context *pipe = ctx->base.pipe;
705
706 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
707
708 if (int_format) {
709 if (!ctx->fs_col_int[num_cbufs])
710 ctx->fs_col_int[num_cbufs] =
711 util_make_fragment_cloneinput_shader(pipe, num_cbufs,
712 TGSI_SEMANTIC_GENERIC,
713 TGSI_INTERPOLATE_CONSTANT);
714 return ctx->fs_col_int[num_cbufs];
715 } else {
716 if (!ctx->fs_col[num_cbufs])
717 ctx->fs_col[num_cbufs] =
718 util_make_fragment_cloneinput_shader(pipe, num_cbufs,
719 TGSI_SEMANTIC_GENERIC,
720 TGSI_INTERPOLATE_LINEAR);
721 return ctx->fs_col[num_cbufs];
722 }
723 }
724
725 static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
726 enum pipe_texture_target target,
727 unsigned nr_samples)
728 {
729 struct pipe_context *pipe = ctx->base.pipe;
730
731 assert(target < PIPE_MAX_TEXTURE_TYPES);
732
733 if (nr_samples > 1) {
734 void **shader = &ctx->fs_texfetch_col_msaa[target];
735
736 /* Create the fragment shader on-demand. */
737 if (!*shader) {
738 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
739 nr_samples);
740
741 *shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex);
742 }
743
744 return *shader;
745 } else {
746 void **shader = &ctx->fs_texfetch_col[target];
747
748 /* Create the fragment shader on-demand. */
749 if (!*shader) {
750 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
751
752 *shader =
753 util_make_fragment_tex_shader(pipe, tgsi_tex,
754 TGSI_INTERPOLATE_LINEAR);
755 }
756
757 return *shader;
758 }
759 }
760
761 static INLINE
762 void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
763 enum pipe_texture_target target,
764 unsigned nr_samples)
765 {
766 struct pipe_context *pipe = ctx->base.pipe;
767
768 assert(target < PIPE_MAX_TEXTURE_TYPES);
769
770 if (nr_samples > 1) {
771 void **shader = &ctx->fs_texfetch_depth_msaa[target];
772
773 /* Create the fragment shader on-demand. */
774 if (!*shader) {
775 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
776 nr_samples);
777
778 *shader =
779 util_make_fs_blit_msaa_depth(pipe, tgsi_tex);
780 }
781
782 return *shader;
783 } else {
784 void **shader = &ctx->fs_texfetch_depth[target];
785
786 /* Create the fragment shader on-demand. */
787 if (!*shader) {
788 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
789
790 *shader =
791 util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex,
792 TGSI_INTERPOLATE_LINEAR);
793 }
794
795 return *shader;
796 }
797 }
798
799 static INLINE
800 void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
801 enum pipe_texture_target target,
802 unsigned nr_samples)
803 {
804 struct pipe_context *pipe = ctx->base.pipe;
805
806 assert(target < PIPE_MAX_TEXTURE_TYPES);
807
808 if (nr_samples > 1) {
809 void **shader = &ctx->fs_texfetch_depthstencil_msaa[target];
810
811 /* Create the fragment shader on-demand. */
812 if (!*shader) {
813 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
814 nr_samples);
815
816 *shader =
817 util_make_fs_blit_msaa_depthstencil(pipe, tgsi_tex);
818 }
819
820 return *shader;
821 } else {
822 void **shader = &ctx->fs_texfetch_depthstencil[target];
823
824 /* Create the fragment shader on-demand. */
825 if (!*shader) {
826 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
827
828 *shader =
829 util_make_fragment_tex_shader_writedepthstencil(pipe, tgsi_tex,
830 TGSI_INTERPOLATE_LINEAR);
831 }
832
833 return *shader;
834 }
835 }
836
837 static INLINE
838 void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
839 enum pipe_texture_target target,
840 unsigned nr_samples)
841 {
842 struct pipe_context *pipe = ctx->base.pipe;
843
844 assert(target < PIPE_MAX_TEXTURE_TYPES);
845
846 if (nr_samples > 1) {
847 void **shader = &ctx->fs_texfetch_stencil_msaa[target];
848
849 /* Create the fragment shader on-demand. */
850 if (!*shader) {
851 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
852 nr_samples);
853
854 *shader =
855 util_make_fs_blit_msaa_stencil(pipe, tgsi_tex);
856 }
857
858 return *shader;
859 } else {
860 void **shader = &ctx->fs_texfetch_stencil[target];
861
862 /* Create the fragment shader on-demand. */
863 if (!*shader) {
864 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
865
866 *shader =
867 util_make_fragment_tex_shader_writestencil(pipe, tgsi_tex,
868 TGSI_INTERPOLATE_LINEAR);
869 }
870
871 return *shader;
872 }
873 }
874
875 void util_blitter_cache_all_shaders(struct blitter_context *blitter)
876 {
877 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
878 struct pipe_screen *screen = blitter->pipe->screen;
879 unsigned num_cbufs, i, target, max_samples;
880 boolean has_arraytex;
881
882 num_cbufs = MAX2(screen->get_param(screen,
883 PIPE_CAP_MAX_RENDER_TARGETS), 1);
884 max_samples = ctx->has_texture_multisample ? 2 : 1;
885 has_arraytex = screen->get_param(screen,
886 PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS) != 0;
887
888 for (i = 0; i < num_cbufs; i++) {
889 blitter_get_fs_col(ctx, i, FALSE);
890 blitter_get_fs_col(ctx, i, TRUE);
891 }
892
893 /* It only matters if i <= 1 or > 1. */
894 for (i = 1; i <= max_samples; i++) {
895 for (target = PIPE_TEXTURE_1D; target < PIPE_MAX_TEXTURE_TYPES; target++) {
896 if (!has_arraytex &&
897 (target == PIPE_TEXTURE_1D_ARRAY ||
898 target == PIPE_TEXTURE_2D_ARRAY)) {
899 continue;
900 }
901
902 blitter_get_fs_texfetch_col(ctx, target, i);
903 blitter_get_fs_texfetch_depth(ctx, target, i);
904 if (ctx->has_stencil_export) {
905 blitter_get_fs_texfetch_depthstencil(ctx, target, i);
906 blitter_get_fs_texfetch_stencil(ctx, target, i);
907 }
908 }
909 }
910 }
911
912 static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx,
913 boolean scissor)
914 {
915 struct pipe_context *pipe = ctx->base.pipe;
916
917 pipe->bind_rasterizer_state(pipe, scissor ? ctx->rs_state_scissor
918 : ctx->rs_state);
919 pipe->bind_vs_state(pipe, ctx->vs);
920 if (ctx->has_geometry_shader)
921 pipe->bind_gs_state(pipe, NULL);
922 if (ctx->has_stream_out)
923 pipe->set_stream_output_targets(pipe, 0, NULL, 0);
924 }
925
926 static void blitter_draw(struct blitter_context_priv *ctx,
927 int x1, int y1, int x2, int y2, float depth)
928 {
929 struct pipe_resource *buf = NULL;
930 unsigned offset = 0;
931
932 blitter_set_rectangle(ctx, x1, y1, x2, y2, depth);
933
934 u_upload_data(ctx->upload, 0, sizeof(ctx->vertices), ctx->vertices,
935 &offset, &buf);
936 u_upload_unmap(ctx->upload);
937 util_draw_vertex_buffer(ctx->base.pipe, NULL, buf, ctx->base.vb_slot,
938 offset, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
939 pipe_resource_reference(&buf, NULL);
940 }
941
942 void util_blitter_draw_rectangle(struct blitter_context *blitter,
943 int x1, int y1, int x2, int y2, float depth,
944 enum blitter_attrib_type type,
945 const union pipe_color_union *attrib)
946 {
947 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
948
949 switch (type) {
950 case UTIL_BLITTER_ATTRIB_COLOR:
951 blitter_set_clear_color(ctx, attrib);
952 break;
953
954 case UTIL_BLITTER_ATTRIB_TEXCOORD:
955 set_texcoords_in_vertices(attrib->f, &ctx->vertices[0][1][0], 8);
956 break;
957
958 default:;
959 }
960
961 blitter_draw(ctx, x1, y1, x2, y2, depth);
962 }
963
964 static void util_blitter_clear_custom(struct blitter_context *blitter,
965 unsigned width, unsigned height,
966 unsigned num_cbufs,
967 unsigned clear_buffers,
968 enum pipe_format cbuf_format,
969 const union pipe_color_union *color,
970 double depth, unsigned stencil,
971 void *custom_blend, void *custom_dsa)
972 {
973 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
974 struct pipe_context *pipe = ctx->base.pipe;
975 struct pipe_stencil_ref sr = { { 0 } };
976 boolean int_format = util_format_is_pure_integer(cbuf_format);
977 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
978
979 blitter_set_running_flag(ctx);
980 blitter_check_saved_vertex_states(ctx);
981 blitter_check_saved_fragment_states(ctx);
982 blitter_disable_render_cond(ctx);
983
984 /* bind states */
985 if (custom_blend) {
986 pipe->bind_blend_state(pipe, custom_blend);
987 } else if (clear_buffers & PIPE_CLEAR_COLOR) {
988 pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA]);
989 } else {
990 pipe->bind_blend_state(pipe, ctx->blend[0]);
991 }
992
993 if (custom_dsa) {
994 pipe->bind_depth_stencil_alpha_state(pipe, custom_dsa);
995 } else if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
996 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
997 } else if (clear_buffers & PIPE_CLEAR_DEPTH) {
998 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
999 } else if (clear_buffers & PIPE_CLEAR_STENCIL) {
1000 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
1001 } else {
1002 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
1003 }
1004
1005 sr.ref_value[0] = stencil & 0xff;
1006 pipe->set_stencil_ref(pipe, &sr);
1007
1008 if (util_format_is_pure_sint(cbuf_format)) {
1009 pipe->bind_vertex_elements_state(pipe, ctx->velem_sint_state);
1010 } else if (util_format_is_pure_uint(cbuf_format)) {
1011 pipe->bind_vertex_elements_state(pipe, ctx->velem_uint_state);
1012 } else {
1013 pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1014 }
1015 ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs, int_format));
1016 pipe->set_sample_mask(pipe, ~0);
1017
1018 blitter_set_common_draw_rect_state(ctx, FALSE);
1019 blitter_set_dst_dimensions(ctx, width, height);
1020 blitter->draw_rectangle(blitter, 0, 0, width, height, (float) depth,
1021 UTIL_BLITTER_ATTRIB_COLOR, color);
1022
1023 blitter_restore_vertex_states(ctx);
1024 blitter_restore_fragment_states(ctx);
1025 blitter_restore_render_cond(ctx);
1026 blitter_unset_running_flag(ctx);
1027 }
1028
1029 void util_blitter_clear(struct blitter_context *blitter,
1030 unsigned width, unsigned height,
1031 unsigned num_cbufs,
1032 unsigned clear_buffers,
1033 enum pipe_format cbuf_format,
1034 const union pipe_color_union *color,
1035 double depth, unsigned stencil)
1036 {
1037 util_blitter_clear_custom(blitter, width, height, num_cbufs,
1038 clear_buffers, cbuf_format, color, depth, stencil,
1039 NULL, NULL);
1040 }
1041
1042 void util_blitter_custom_clear_depth(struct blitter_context *blitter,
1043 unsigned width, unsigned height,
1044 double depth, void *custom_dsa)
1045 {
1046 static const union pipe_color_union color;
1047 util_blitter_clear_custom(blitter, width, height, 0,
1048 0, PIPE_FORMAT_NONE, &color, depth, 0, NULL, custom_dsa);
1049 }
1050
1051 static
1052 boolean is_overlap(int dstx, int dsty, int dstz,
1053 const struct pipe_box *srcbox)
1054 {
1055 struct pipe_box src = *srcbox;
1056
1057 if (src.width < 0) {
1058 src.x += src.width;
1059 src.width = -src.width;
1060 }
1061 if (src.height < 0) {
1062 src.y += src.height;
1063 src.height = -src.height;
1064 }
1065 if (src.depth < 0) {
1066 src.z += src.depth;
1067 src.depth = -src.depth;
1068 }
1069 return src.x < dstx+src.width && src.x+src.width > dstx &&
1070 src.y < dsty+src.height && src.y+src.height > dsty &&
1071 src.z < dstz+src.depth && src.z+src.depth > dstz;
1072 }
1073
1074 void util_blitter_default_dst_texture(struct pipe_surface *dst_templ,
1075 struct pipe_resource *dst,
1076 unsigned dstlevel,
1077 unsigned dstz,
1078 const struct pipe_box *srcbox)
1079 {
1080 memset(dst_templ, 0, sizeof(*dst_templ));
1081 dst_templ->format = dst->format;
1082 if (util_format_is_depth_or_stencil(dst->format)) {
1083 dst_templ->usage = PIPE_BIND_DEPTH_STENCIL;
1084 } else {
1085 dst_templ->usage = PIPE_BIND_RENDER_TARGET;
1086 }
1087 dst_templ->format = util_format_linear(dst->format);
1088 dst_templ->u.tex.level = dstlevel;
1089 dst_templ->u.tex.first_layer = dstz;
1090 dst_templ->u.tex.last_layer = dstz + srcbox->depth - 1;
1091 }
1092
1093 void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ,
1094 struct pipe_resource *src,
1095 unsigned srclevel)
1096 {
1097 memset(src_templ, 0, sizeof(*src_templ));
1098 src_templ->format = util_format_linear(src->format);
1099 src_templ->u.tex.first_level = srclevel;
1100 src_templ->u.tex.last_level = srclevel;
1101 src_templ->u.tex.first_layer = 0;
1102 src_templ->u.tex.last_layer =
1103 src->target == PIPE_TEXTURE_3D ? u_minify(src->depth0, srclevel) - 1
1104 : src->array_size - 1;
1105 src_templ->swizzle_r = PIPE_SWIZZLE_RED;
1106 src_templ->swizzle_g = PIPE_SWIZZLE_GREEN;
1107 src_templ->swizzle_b = PIPE_SWIZZLE_BLUE;
1108 src_templ->swizzle_a = PIPE_SWIZZLE_ALPHA;
1109 }
1110
1111 static boolean is_blit_generic_supported(struct blitter_context *blitter,
1112 const struct pipe_resource *dst,
1113 enum pipe_format dst_format,
1114 const struct pipe_resource *src,
1115 enum pipe_format src_format,
1116 unsigned mask)
1117 {
1118 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1119 struct pipe_screen *screen = ctx->base.pipe->screen;
1120
1121 if (dst) {
1122 unsigned bind;
1123 boolean is_stencil;
1124 const struct util_format_description *desc =
1125 util_format_description(dst_format);
1126
1127 is_stencil = util_format_has_stencil(desc);
1128
1129 /* Stencil export must be supported for stencil copy. */
1130 if ((mask & PIPE_MASK_S) && is_stencil && !ctx->has_stencil_export) {
1131 return FALSE;
1132 }
1133
1134 if (is_stencil || util_format_has_depth(desc))
1135 bind = PIPE_BIND_DEPTH_STENCIL;
1136 else
1137 bind = PIPE_BIND_RENDER_TARGET;
1138
1139 if (!screen->is_format_supported(screen, dst_format, dst->target,
1140 dst->nr_samples, bind)) {
1141 return FALSE;
1142 }
1143 }
1144
1145 if (src) {
1146 if (src->nr_samples > 1 && !ctx->has_texture_multisample) {
1147 return FALSE;
1148 }
1149
1150 if (!screen->is_format_supported(screen, src_format, src->target,
1151 src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) {
1152 return FALSE;
1153 }
1154
1155 /* Check stencil sampler support for stencil copy. */
1156 if (util_format_has_stencil(util_format_description(src_format))) {
1157 enum pipe_format stencil_format =
1158 util_format_stencil_only(src_format);
1159 assert(stencil_format != PIPE_FORMAT_NONE);
1160
1161 if (stencil_format != src_format &&
1162 !screen->is_format_supported(screen, stencil_format, src->target,
1163 src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) {
1164 return FALSE;
1165 }
1166 }
1167 }
1168
1169 return TRUE;
1170 }
1171
1172 boolean util_blitter_is_copy_supported(struct blitter_context *blitter,
1173 const struct pipe_resource *dst,
1174 const struct pipe_resource *src,
1175 unsigned mask)
1176 {
1177 return is_blit_generic_supported(blitter, dst, dst->format,
1178 src, src->format, mask);
1179 }
1180
1181 boolean util_blitter_is_blit_supported(struct blitter_context *blitter,
1182 const struct pipe_blit_info *info)
1183 {
1184 return is_blit_generic_supported(blitter,
1185 info->dst.resource, info->dst.format,
1186 info->src.resource, info->src.format,
1187 info->mask);
1188 }
1189
1190 void util_blitter_copy_texture(struct blitter_context *blitter,
1191 struct pipe_resource *dst,
1192 unsigned dst_level,
1193 unsigned dstx, unsigned dsty, unsigned dstz,
1194 struct pipe_resource *src,
1195 unsigned src_level,
1196 const struct pipe_box *srcbox, unsigned mask,
1197 boolean copy_all_samples)
1198 {
1199 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1200 struct pipe_context *pipe = ctx->base.pipe;
1201 struct pipe_surface *dst_view, dst_templ;
1202 struct pipe_sampler_view src_templ, *src_view;
1203
1204 assert(dst && src);
1205 assert(src->target < PIPE_MAX_TEXTURE_TYPES);
1206
1207 /* Initialize the surface. */
1208 util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz, srcbox);
1209 dst_view = pipe->create_surface(pipe, dst, &dst_templ);
1210
1211 /* Initialize the sampler view. */
1212 util_blitter_default_src_texture(&src_templ, src, src_level);
1213 src_view = pipe->create_sampler_view(pipe, src, &src_templ);
1214
1215 /* Copy. */
1216 util_blitter_blit_generic(blitter, dst_view, dstx, dsty,
1217 abs(srcbox->width), abs(srcbox->height),
1218 src_view, srcbox, src->width0, src->height0,
1219 mask, PIPE_TEX_FILTER_NEAREST, NULL,
1220 copy_all_samples);
1221
1222 pipe_surface_reference(&dst_view, NULL);
1223 pipe_sampler_view_reference(&src_view, NULL);
1224 }
1225
1226 void util_blitter_blit_generic(struct blitter_context *blitter,
1227 struct pipe_surface *dst,
1228 int dstx, int dsty,
1229 unsigned dst_width, unsigned dst_height,
1230 struct pipe_sampler_view *src,
1231 const struct pipe_box *srcbox,
1232 unsigned src_width0, unsigned src_height0,
1233 unsigned mask, unsigned filter,
1234 const struct pipe_scissor_state *scissor,
1235 boolean copy_all_samples)
1236 {
1237 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1238 struct pipe_context *pipe = ctx->base.pipe;
1239 struct pipe_framebuffer_state fb_state;
1240 enum pipe_texture_target src_target = src->texture->target;
1241 boolean has_depth, has_stencil, has_color;
1242 boolean blit_stencil, blit_depth, blit_color;
1243 void *sampler_state;
1244 const struct util_format_description *src_desc =
1245 util_format_description(src->format);
1246 const struct util_format_description *dst_desc =
1247 util_format_description(dst->format);
1248
1249 has_color = src_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS &&
1250 dst_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS;
1251 has_depth = util_format_has_depth(src_desc) &&
1252 util_format_has_depth(dst_desc);
1253 has_stencil = util_format_has_stencil(src_desc) &&
1254 util_format_has_stencil(dst_desc);
1255
1256 blit_color = has_color && (mask & PIPE_MASK_RGBA);
1257 blit_depth = has_depth && (mask & PIPE_MASK_Z);
1258 blit_stencil = has_stencil && (mask & PIPE_MASK_S) &&
1259 ctx->has_stencil_export;
1260
1261 if (!blit_stencil && !blit_depth && !blit_color) {
1262 return;
1263 }
1264
1265 /* Sanity checks. */
1266 if (dst->texture == src->texture &&
1267 dst->u.tex.level == src->u.tex.first_level) {
1268 assert(!is_overlap(dstx, dsty, 0, srcbox));
1269 }
1270 /* XXX should handle 3d regions */
1271 assert(srcbox->depth == 1);
1272
1273 /* Check whether the states are properly saved. */
1274 blitter_set_running_flag(ctx);
1275 blitter_check_saved_vertex_states(ctx);
1276 blitter_check_saved_fragment_states(ctx);
1277 blitter_check_saved_textures(ctx);
1278 blitter_check_saved_fb_state(ctx);
1279 blitter_disable_render_cond(ctx);
1280
1281 /* Initialize framebuffer state. */
1282 fb_state.width = dst->width;
1283 fb_state.height = dst->height;
1284
1285 if (blit_depth || blit_stencil) {
1286 pipe->bind_blend_state(pipe, ctx->blend[0]);
1287
1288 if (blit_depth && blit_stencil) {
1289 pipe->bind_depth_stencil_alpha_state(pipe,
1290 ctx->dsa_write_depth_stencil);
1291 ctx->bind_fs_state(pipe,
1292 blitter_get_fs_texfetch_depthstencil(ctx, src->texture->target,
1293 src->texture->nr_samples));
1294 } else if (blit_depth) {
1295 pipe->bind_depth_stencil_alpha_state(pipe,
1296 ctx->dsa_write_depth_keep_stencil);
1297 ctx->bind_fs_state(pipe,
1298 blitter_get_fs_texfetch_depth(ctx, src->texture->target,
1299 src->texture->nr_samples));
1300 } else { /* is_stencil */
1301 pipe->bind_depth_stencil_alpha_state(pipe,
1302 ctx->dsa_keep_depth_write_stencil);
1303 ctx->bind_fs_state(pipe,
1304 blitter_get_fs_texfetch_stencil(ctx, src->texture->target,
1305 src->texture->nr_samples));
1306 }
1307
1308 fb_state.nr_cbufs = 0;
1309 fb_state.zsbuf = dst;
1310 } else {
1311 pipe->bind_blend_state(pipe, ctx->blend[mask & PIPE_MASK_RGBA]);
1312 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
1313 ctx->bind_fs_state(pipe,
1314 blitter_get_fs_texfetch_col(ctx, src->texture->target,
1315 src->texture->nr_samples));
1316
1317 fb_state.nr_cbufs = 1;
1318 fb_state.cbufs[0] = dst;
1319 fb_state.zsbuf = 0;
1320 }
1321
1322 /* Set the linear filter only for scaled color non-MSAA blits. */
1323 if (filter == PIPE_TEX_FILTER_LINEAR &&
1324 !blit_depth && !blit_stencil &&
1325 src->texture->nr_samples <= 1 &&
1326 (dst_width != abs(srcbox->width) || dst_height != abs(srcbox->height))) {
1327 sampler_state = ctx->sampler_state_linear;
1328 } else {
1329 sampler_state = ctx->sampler_state;
1330 }
1331
1332 /* Set samplers. */
1333 if (blit_depth && blit_stencil) {
1334 /* Setup two samplers, one for depth and the other one for stencil. */
1335 struct pipe_sampler_view templ;
1336 struct pipe_sampler_view *views[2];
1337 void *samplers[2] = {sampler_state, sampler_state};
1338
1339 templ = *src;
1340 templ.format = util_format_stencil_only(templ.format);
1341 assert(templ.format != PIPE_FORMAT_NONE);
1342
1343 views[0] = src;
1344 views[1] = pipe->create_sampler_view(pipe, src->texture, &templ);
1345
1346 pipe->set_fragment_sampler_views(pipe, 2, views);
1347 pipe->bind_fragment_sampler_states(pipe, 2, samplers);
1348
1349 pipe_sampler_view_reference(&views[1], NULL);
1350 } else if (blit_stencil) {
1351 /* Set a stencil-only sampler view for it not to sample depth instead. */
1352 struct pipe_sampler_view templ;
1353 struct pipe_sampler_view *view;
1354
1355 templ = *src;
1356 templ.format = util_format_stencil_only(templ.format);
1357 assert(templ.format != PIPE_FORMAT_NONE);
1358
1359 view = pipe->create_sampler_view(pipe, src->texture, &templ);
1360
1361 pipe->set_fragment_sampler_views(pipe, 1, &view);
1362 pipe->bind_fragment_sampler_states(pipe, 1, &sampler_state);
1363
1364 pipe_sampler_view_reference(&view, NULL);
1365 } else {
1366 pipe->set_fragment_sampler_views(pipe, 1, &src);
1367 pipe->bind_fragment_sampler_states(pipe, 1, &sampler_state);
1368 }
1369
1370 pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1371 pipe->set_framebuffer_state(pipe, &fb_state);
1372
1373 if (scissor) {
1374 pipe->set_scissor_state(pipe, scissor);
1375 }
1376
1377 blitter_set_common_draw_rect_state(ctx, scissor != NULL);
1378 blitter_set_dst_dimensions(ctx, dst->width, dst->height);
1379
1380 if ((src_target == PIPE_TEXTURE_1D ||
1381 src_target == PIPE_TEXTURE_2D ||
1382 src_target == PIPE_TEXTURE_RECT) &&
1383 src->texture->nr_samples <= 1) {
1384 /* Draw the quad with the draw_rectangle callback. */
1385
1386 /* Set texture coordinates. - use a pipe color union
1387 * for interface purposes.
1388 * XXX pipe_color_union is a wrong name since we use that to set
1389 * texture coordinates too.
1390 */
1391 union pipe_color_union coord;
1392 get_texcoords(src, src_width0, src_height0, srcbox->x, srcbox->y,
1393 srcbox->x+srcbox->width, srcbox->y+srcbox->height, coord.f);
1394
1395 /* Draw. */
1396 pipe->set_sample_mask(pipe, ~0);
1397 blitter->draw_rectangle(blitter, dstx, dsty,
1398 dstx+dst_width, dsty+dst_height, 0,
1399 UTIL_BLITTER_ATTRIB_TEXCOORD, &coord);
1400 } else {
1401 /* Draw the quad with the generic codepath. */
1402 if (copy_all_samples &&
1403 src->texture->nr_samples == dst->texture->nr_samples &&
1404 dst->texture->nr_samples > 1) {
1405 /* MSAA copy. */
1406 unsigned i, max_sample = MAX2(dst->texture->nr_samples, 1) - 1;
1407
1408 for (i = 0; i <= max_sample; i++) {
1409 pipe->set_sample_mask(pipe, 1 << i);
1410 blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z,
1411 i, srcbox->x, srcbox->y,
1412 srcbox->x + srcbox->width,
1413 srcbox->y + srcbox->height);
1414 blitter_draw(ctx, dstx, dsty,
1415 dstx+dst_width, dsty+dst_height, 0);
1416 }
1417 } else {
1418 pipe->set_sample_mask(pipe, ~0);
1419 blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z, 0,
1420 srcbox->x, srcbox->y,
1421 srcbox->x + srcbox->width,
1422 srcbox->y + srcbox->height);
1423 blitter_draw(ctx, dstx, dsty, dstx+dst_width, dsty+dst_height, 0);
1424 }
1425 }
1426
1427 blitter_restore_vertex_states(ctx);
1428 blitter_restore_fragment_states(ctx);
1429 blitter_restore_textures(ctx);
1430 blitter_restore_fb_state(ctx);
1431 if (scissor) {
1432 pipe->set_scissor_state(pipe, &ctx->base.saved_scissor);
1433 }
1434 blitter_restore_render_cond(ctx);
1435 blitter_unset_running_flag(ctx);
1436 }
1437
1438 void
1439 util_blitter_blit(struct blitter_context *blitter,
1440 const struct pipe_blit_info *info)
1441 {
1442 struct pipe_resource *dst = info->dst.resource;
1443 struct pipe_resource *src = info->src.resource;
1444 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1445 struct pipe_context *pipe = ctx->base.pipe;
1446 struct pipe_surface *dst_view, dst_templ;
1447 struct pipe_sampler_view src_templ, *src_view;
1448
1449 /* Initialize the surface. */
1450 util_blitter_default_dst_texture(&dst_templ, dst, info->dst.level,
1451 info->dst.box.z, &info->src.box);
1452 dst_templ.format = info->dst.format;
1453 dst_view = pipe->create_surface(pipe, dst, &dst_templ);
1454
1455 /* Initialize the sampler view. */
1456 util_blitter_default_src_texture(&src_templ, src, info->src.level);
1457 src_templ.format = info->src.format;
1458 src_view = pipe->create_sampler_view(pipe, src, &src_templ);
1459
1460 /* Copy. */
1461 util_blitter_blit_generic(blitter, dst_view,
1462 info->dst.box.x, info->dst.box.y,
1463 info->dst.box.width, info->dst.box.height,
1464 src_view, &info->src.box, src->width0, src->height0,
1465 info->mask, info->filter,
1466 info->scissor_enable ? &info->scissor : NULL, TRUE);
1467
1468 pipe_surface_reference(&dst_view, NULL);
1469 pipe_sampler_view_reference(&src_view, NULL);
1470 }
1471
1472 /* Clear a region of a color surface to a constant value. */
1473 void util_blitter_clear_render_target(struct blitter_context *blitter,
1474 struct pipe_surface *dstsurf,
1475 const union pipe_color_union *color,
1476 unsigned dstx, unsigned dsty,
1477 unsigned width, unsigned height)
1478 {
1479 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1480 struct pipe_context *pipe = ctx->base.pipe;
1481 struct pipe_framebuffer_state fb_state;
1482
1483 assert(dstsurf->texture);
1484 if (!dstsurf->texture)
1485 return;
1486
1487 /* check the saved state */
1488 blitter_set_running_flag(ctx);
1489 blitter_check_saved_vertex_states(ctx);
1490 blitter_check_saved_fragment_states(ctx);
1491 blitter_check_saved_fb_state(ctx);
1492 blitter_disable_render_cond(ctx);
1493
1494 /* bind states */
1495 pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA]);
1496 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
1497 ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
1498 pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1499
1500 /* set a framebuffer state */
1501 fb_state.width = dstsurf->width;
1502 fb_state.height = dstsurf->height;
1503 fb_state.nr_cbufs = 1;
1504 fb_state.cbufs[0] = dstsurf;
1505 fb_state.zsbuf = 0;
1506 pipe->set_framebuffer_state(pipe, &fb_state);
1507 pipe->set_sample_mask(pipe, ~0);
1508
1509 blitter_set_common_draw_rect_state(ctx, FALSE);
1510 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
1511 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
1512 UTIL_BLITTER_ATTRIB_COLOR, color);
1513
1514 blitter_restore_vertex_states(ctx);
1515 blitter_restore_fragment_states(ctx);
1516 blitter_restore_fb_state(ctx);
1517 blitter_restore_render_cond(ctx);
1518 blitter_unset_running_flag(ctx);
1519 }
1520
1521 /* Clear a region of a depth stencil surface. */
1522 void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
1523 struct pipe_surface *dstsurf,
1524 unsigned clear_flags,
1525 double depth,
1526 unsigned stencil,
1527 unsigned dstx, unsigned dsty,
1528 unsigned width, unsigned height)
1529 {
1530 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1531 struct pipe_context *pipe = ctx->base.pipe;
1532 struct pipe_framebuffer_state fb_state;
1533 struct pipe_stencil_ref sr = { { 0 } };
1534
1535 assert(dstsurf->texture);
1536 if (!dstsurf->texture)
1537 return;
1538
1539 /* check the saved state */
1540 blitter_set_running_flag(ctx);
1541 blitter_check_saved_vertex_states(ctx);
1542 blitter_check_saved_fragment_states(ctx);
1543 blitter_check_saved_fb_state(ctx);
1544 blitter_disable_render_cond(ctx);
1545
1546 /* bind states */
1547 pipe->bind_blend_state(pipe, ctx->blend[0]);
1548 if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
1549 sr.ref_value[0] = stencil & 0xff;
1550 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
1551 pipe->set_stencil_ref(pipe, &sr);
1552 }
1553 else if (clear_flags & PIPE_CLEAR_DEPTH) {
1554 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
1555 }
1556 else if (clear_flags & PIPE_CLEAR_STENCIL) {
1557 sr.ref_value[0] = stencil & 0xff;
1558 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
1559 pipe->set_stencil_ref(pipe, &sr);
1560 }
1561 else
1562 /* hmm that should be illegal probably, or make it a no-op somewhere */
1563 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
1564
1565 ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE));
1566 pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1567
1568 /* set a framebuffer state */
1569 fb_state.width = dstsurf->width;
1570 fb_state.height = dstsurf->height;
1571 fb_state.nr_cbufs = 0;
1572 fb_state.cbufs[0] = 0;
1573 fb_state.zsbuf = dstsurf;
1574 pipe->set_framebuffer_state(pipe, &fb_state);
1575 pipe->set_sample_mask(pipe, ~0);
1576
1577 blitter_set_common_draw_rect_state(ctx, FALSE);
1578 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
1579 blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height,
1580 (float) depth,
1581 UTIL_BLITTER_ATTRIB_NONE, NULL);
1582
1583 blitter_restore_vertex_states(ctx);
1584 blitter_restore_fragment_states(ctx);
1585 blitter_restore_fb_state(ctx);
1586 blitter_restore_render_cond(ctx);
1587 blitter_unset_running_flag(ctx);
1588 }
1589
1590 /* draw a rectangle across a region using a custom dsa stage - for r600g */
1591 void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
1592 struct pipe_surface *zsurf,
1593 struct pipe_surface *cbsurf,
1594 unsigned sample_mask,
1595 void *dsa_stage, float depth)
1596 {
1597 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1598 struct pipe_context *pipe = ctx->base.pipe;
1599 struct pipe_framebuffer_state fb_state;
1600
1601 assert(zsurf->texture);
1602 if (!zsurf->texture)
1603 return;
1604
1605 /* check the saved state */
1606 blitter_set_running_flag(ctx);
1607 blitter_check_saved_vertex_states(ctx);
1608 blitter_check_saved_fragment_states(ctx);
1609 blitter_check_saved_fb_state(ctx);
1610 blitter_disable_render_cond(ctx);
1611
1612 /* bind states */
1613 pipe->bind_blend_state(pipe, cbsurf ? ctx->blend[PIPE_MASK_RGBA] :
1614 ctx->blend[0]);
1615 pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);
1616 ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE));
1617 pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1618
1619 /* set a framebuffer state */
1620 fb_state.width = zsurf->width;
1621 fb_state.height = zsurf->height;
1622 fb_state.nr_cbufs = 1;
1623 if (cbsurf) {
1624 fb_state.cbufs[0] = cbsurf;
1625 fb_state.nr_cbufs = 1;
1626 } else {
1627 fb_state.cbufs[0] = NULL;
1628 fb_state.nr_cbufs = 0;
1629 }
1630 fb_state.zsbuf = zsurf;
1631 pipe->set_framebuffer_state(pipe, &fb_state);
1632 pipe->set_sample_mask(pipe, sample_mask);
1633
1634 blitter_set_common_draw_rect_state(ctx, FALSE);
1635 blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height);
1636 blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth,
1637 UTIL_BLITTER_ATTRIB_NONE, NULL);
1638
1639 blitter_restore_vertex_states(ctx);
1640 blitter_restore_fragment_states(ctx);
1641 blitter_restore_fb_state(ctx);
1642 blitter_restore_render_cond(ctx);
1643 blitter_unset_running_flag(ctx);
1644 }
1645
1646 void util_blitter_copy_buffer(struct blitter_context *blitter,
1647 struct pipe_resource *dst,
1648 unsigned dstx,
1649 struct pipe_resource *src,
1650 unsigned srcx,
1651 unsigned size)
1652 {
1653 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1654 struct pipe_context *pipe = ctx->base.pipe;
1655 struct pipe_vertex_buffer vb;
1656 struct pipe_stream_output_target *so_target;
1657
1658 if (srcx >= src->width0 ||
1659 dstx >= dst->width0) {
1660 return;
1661 }
1662 if (srcx + size > src->width0) {
1663 size = src->width0 - srcx;
1664 }
1665 if (dstx + size > dst->width0) {
1666 size = dst->width0 - dstx;
1667 }
1668
1669 /* Drivers not capable of Stream Out should not call this function
1670 * in the first place. */
1671 assert(ctx->has_stream_out);
1672
1673 /* Some alignment is required. */
1674 if (srcx % 4 != 0 || dstx % 4 != 0 || size % 4 != 0 ||
1675 !ctx->has_stream_out) {
1676 struct pipe_box box;
1677 u_box_1d(srcx, size, &box);
1678 util_resource_copy_region(pipe, dst, 0, dstx, 0, 0, src, 0, &box);
1679 return;
1680 }
1681
1682 blitter_set_running_flag(ctx);
1683 blitter_check_saved_vertex_states(ctx);
1684 blitter_disable_render_cond(ctx);
1685
1686 vb.buffer = src;
1687 vb.buffer_offset = srcx;
1688 vb.stride = 4;
1689
1690 pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb);
1691 pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf);
1692 pipe->bind_vs_state(pipe, ctx->vs_pos_only);
1693 if (ctx->has_geometry_shader)
1694 pipe->bind_gs_state(pipe, NULL);
1695 pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state);
1696
1697 so_target = pipe->create_stream_output_target(pipe, dst, dstx, size);
1698 pipe->set_stream_output_targets(pipe, 1, &so_target, 0);
1699
1700 util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 4);
1701
1702 blitter_restore_vertex_states(ctx);
1703 blitter_restore_render_cond(ctx);
1704 blitter_unset_running_flag(ctx);
1705 pipe_so_target_reference(&so_target, NULL);
1706 }
1707
1708 /* probably radeon specific */
1709 void util_blitter_custom_resolve_color(struct blitter_context *blitter,
1710 struct pipe_resource *dst,
1711 unsigned dst_level,
1712 unsigned dst_layer,
1713 struct pipe_resource *src,
1714 unsigned src_layer,
1715 unsigned sample_mask,
1716 void *custom_blend,
1717 enum pipe_format format)
1718 {
1719 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1720 struct pipe_context *pipe = ctx->base.pipe;
1721 struct pipe_framebuffer_state fb_state;
1722 struct pipe_surface *srcsurf, *dstsurf, surf_tmpl;
1723
1724 blitter_set_running_flag(ctx);
1725 blitter_check_saved_vertex_states(ctx);
1726 blitter_check_saved_fragment_states(ctx);
1727 blitter_disable_render_cond(ctx);
1728
1729 /* bind states */
1730 pipe->bind_blend_state(pipe, custom_blend);
1731 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
1732 pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1733 ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
1734 pipe->set_sample_mask(pipe, sample_mask);
1735
1736 memset(&surf_tmpl, 0, sizeof(surf_tmpl));
1737 surf_tmpl.format = format;
1738 surf_tmpl.u.tex.level = dst_level;
1739 surf_tmpl.u.tex.first_layer = dst_layer;
1740 surf_tmpl.u.tex.last_layer = dst_layer;
1741 surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
1742
1743 dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl);
1744
1745 surf_tmpl.u.tex.level = 0;
1746 surf_tmpl.u.tex.first_layer = src_layer;
1747 surf_tmpl.u.tex.last_layer = src_layer;
1748
1749 srcsurf = pipe->create_surface(pipe, src, &surf_tmpl);
1750
1751 /* set a framebuffer state */
1752 fb_state.width = src->width0;
1753 fb_state.height = src->height0;
1754 fb_state.nr_cbufs = 2;
1755 fb_state.cbufs[0] = srcsurf;
1756 fb_state.cbufs[1] = dstsurf;
1757 fb_state.zsbuf = NULL;
1758 pipe->set_framebuffer_state(pipe, &fb_state);
1759
1760 blitter_set_common_draw_rect_state(ctx, FALSE);
1761 blitter_set_dst_dimensions(ctx, src->width0, src->height0);
1762 blitter->draw_rectangle(blitter, 0, 0, src->width0, src->height0,
1763 0, 0, NULL);
1764 blitter_restore_fb_state(ctx);
1765 blitter_restore_vertex_states(ctx);
1766 blitter_restore_fragment_states(ctx);
1767 blitter_restore_render_cond(ctx);
1768 blitter_unset_running_flag(ctx);
1769
1770 pipe_surface_reference(&srcsurf, NULL);
1771 pipe_surface_reference(&dstsurf, NULL);
1772 }
1773
1774 void util_blitter_custom_color(struct blitter_context *blitter,
1775 struct pipe_surface *dstsurf,
1776 void *custom_blend)
1777 {
1778 struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1779 struct pipe_context *pipe = ctx->base.pipe;
1780 struct pipe_framebuffer_state fb_state;
1781
1782 assert(dstsurf->texture);
1783 if (!dstsurf->texture)
1784 return;
1785
1786 /* check the saved state */
1787 blitter_set_running_flag(ctx);
1788 blitter_check_saved_vertex_states(ctx);
1789 blitter_check_saved_fragment_states(ctx);
1790 blitter_check_saved_fb_state(ctx);
1791 blitter_disable_render_cond(ctx);
1792
1793 /* bind states */
1794 pipe->bind_blend_state(pipe, custom_blend);
1795 pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
1796 ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
1797 pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1798 pipe->set_sample_mask(pipe, (1ull << MAX2(1, dstsurf->texture->nr_samples)) - 1);
1799
1800 /* set a framebuffer state */
1801 fb_state.width = dstsurf->width;
1802 fb_state.height = dstsurf->height;
1803 fb_state.nr_cbufs = 1;
1804 fb_state.cbufs[0] = dstsurf;
1805 fb_state.zsbuf = 0;
1806 pipe->set_framebuffer_state(pipe, &fb_state);
1807 pipe->set_sample_mask(pipe, ~0);
1808
1809 blitter_set_common_draw_rect_state(ctx, FALSE);
1810 blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
1811 blitter->draw_rectangle(blitter, 0, 0, dstsurf->width, dstsurf->height,
1812 0, 0, NULL);
1813
1814 blitter_restore_vertex_states(ctx);
1815 blitter_restore_fragment_states(ctx);
1816 blitter_restore_fb_state(ctx);
1817 blitter_restore_render_cond(ctx);
1818 blitter_unset_running_flag(ctx);
1819 }
1820
1821 /* Return whether this is an RGBA, Z, S, or combined ZS format.
1822 */
1823 static unsigned get_format_mask(enum pipe_format format)
1824 {
1825 const struct util_format_description *desc = util_format_description(format);
1826
1827 assert(desc);
1828
1829 if (util_format_has_depth(desc)) {
1830 if (util_format_has_stencil(desc)) {
1831 return PIPE_MASK_ZS;
1832 } else {
1833 return PIPE_MASK_Z;
1834 }
1835 } else {
1836 if (util_format_has_stencil(desc)) {
1837 return PIPE_MASK_S;
1838 } else {
1839 return PIPE_MASK_RGBA;
1840 }
1841 }
1842 }
1843
1844 /* Return if the box is totally inside the resource.
1845 */
1846 static boolean is_box_inside_resource(const struct pipe_resource *res,
1847 const struct pipe_box *box,
1848 unsigned level)
1849 {
1850 unsigned width = 1, height = 1, depth = 1;
1851
1852 switch (res->target) {
1853 case PIPE_BUFFER:
1854 width = res->width0;
1855 height = 1;
1856 depth = 1;
1857 break;
1858 case PIPE_TEXTURE_1D:
1859 width = u_minify(res->width0, level);
1860 height = 1;
1861 depth = 1;
1862 break;
1863 case PIPE_TEXTURE_2D:
1864 case PIPE_TEXTURE_RECT:
1865 width = u_minify(res->width0, level);
1866 height = u_minify(res->height0, level);
1867 depth = 1;
1868 break;
1869 case PIPE_TEXTURE_3D:
1870 width = u_minify(res->width0, level);
1871 height = u_minify(res->height0, level);
1872 depth = u_minify(res->depth0, level);
1873 break;
1874 case PIPE_TEXTURE_CUBE:
1875 width = u_minify(res->width0, level);
1876 height = u_minify(res->height0, level);
1877 depth = 6;
1878 break;
1879 case PIPE_TEXTURE_1D_ARRAY:
1880 width = u_minify(res->width0, level);
1881 height = 1;
1882 depth = res->array_size;
1883 break;
1884 case PIPE_TEXTURE_2D_ARRAY:
1885 width = u_minify(res->width0, level);
1886 height = u_minify(res->height0, level);
1887 depth = res->array_size;
1888 break;
1889 case PIPE_MAX_TEXTURE_TYPES:;
1890 }
1891
1892 return box->x >= 0 &&
1893 box->x + box->width <= (int) width &&
1894 box->y >= 0 &&
1895 box->y + box->height <= (int) height &&
1896 box->z >= 0 &&
1897 box->z + box->depth <= (int) depth;
1898 }
1899
1900 static unsigned get_sample_count(const struct pipe_resource *res)
1901 {
1902 return res->nr_samples ? res->nr_samples : 1;
1903 }
1904
1905 boolean util_try_blit_via_copy_region(struct pipe_context *ctx,
1906 const struct pipe_blit_info *blit)
1907 {
1908 unsigned mask = get_format_mask(blit->dst.format);
1909
1910 /* No format conversions. */
1911 if (blit->src.resource->format != blit->src.format ||
1912 blit->dst.resource->format != blit->dst.format ||
1913 !util_is_format_compatible(
1914 util_format_description(blit->src.resource->format),
1915 util_format_description(blit->dst.resource->format))) {
1916 return FALSE;
1917 }
1918
1919 /* No masks, no filtering, no scissor. */
1920 if ((blit->mask & mask) != mask ||
1921 blit->filter != PIPE_TEX_FILTER_NEAREST ||
1922 blit->scissor_enable) {
1923 return FALSE;
1924 }
1925
1926 /* No flipping. */
1927 if (blit->src.box.width < 0 ||
1928 blit->src.box.height < 0 ||
1929 blit->src.box.depth < 0) {
1930 return FALSE;
1931 }
1932
1933 /* No scaling. */
1934 if (blit->src.box.width != blit->dst.box.width ||
1935 blit->src.box.height != blit->dst.box.height ||
1936 blit->src.box.depth != blit->dst.box.depth) {
1937 return FALSE;
1938 }
1939
1940 /* No out-of-bounds access. */
1941 if (!is_box_inside_resource(blit->src.resource, &blit->src.box,
1942 blit->src.level) ||
1943 !is_box_inside_resource(blit->dst.resource, &blit->dst.box,
1944 blit->dst.level)) {
1945 return FALSE;
1946 }
1947
1948 /* Sample counts must match. */
1949 if (get_sample_count(blit->src.resource) !=
1950 get_sample_count(blit->dst.resource)) {
1951 return FALSE;
1952 }
1953
1954 ctx->resource_copy_region(ctx, blit->dst.resource, blit->dst.level,
1955 blit->dst.box.x, blit->dst.box.y, blit->dst.box.z,
1956 blit->src.resource, blit->src.level,
1957 &blit->src.box);
1958 return TRUE;
1959 }