util: add casts to silence MSVC warnings in u_blit.c
[mesa.git] / src / gallium / auxiliary / util / u_blit.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * @file
30 * Copy/blit pixel rect between surfaces
31 *
32 * @author Brian Paul
33 */
34
35
36 #include "pipe/p_context.h"
37 #include "util/u_debug.h"
38 #include "pipe/p_defines.h"
39 #include "util/u_inlines.h"
40 #include "pipe/p_shader_tokens.h"
41 #include "pipe/p_state.h"
42
43 #include "util/u_blit.h"
44 #include "util/u_draw_quad.h"
45 #include "util/u_format.h"
46 #include "util/u_math.h"
47 #include "util/u_memory.h"
48 #include "util/u_sampler.h"
49 #include "util/u_simple_shaders.h"
50
51 #include "cso_cache/cso_context.h"
52
53
54 struct blit_state
55 {
56 struct pipe_context *pipe;
57 struct cso_context *cso;
58
59 struct pipe_blend_state blend_write_color, blend_keep_color;
60 struct pipe_depth_stencil_alpha_state dsa_keep_depthstencil;
61 struct pipe_depth_stencil_alpha_state dsa_write_depthstencil;
62 struct pipe_depth_stencil_alpha_state dsa_write_depth;
63 struct pipe_depth_stencil_alpha_state dsa_write_stencil;
64 struct pipe_rasterizer_state rasterizer;
65 struct pipe_sampler_state sampler;
66 struct pipe_viewport_state viewport;
67 struct pipe_vertex_element velem[2];
68 enum pipe_texture_target internal_target;
69
70 void *vs;
71 void *fs[PIPE_MAX_TEXTURE_TYPES][TGSI_WRITEMASK_XYZW + 1];
72 void *fs_depthstencil[PIPE_MAX_TEXTURE_TYPES];
73 void *fs_depth[PIPE_MAX_TEXTURE_TYPES];
74 void *fs_stencil[PIPE_MAX_TEXTURE_TYPES];
75
76 struct pipe_resource *vbuf; /**< quad vertices */
77 unsigned vbuf_slot;
78
79 float vertices[4][2][4]; /**< vertex/texcoords for quad */
80
81 boolean has_stencil_export;
82 };
83
84
85 /**
86 * Create state object for blit.
87 * Intended to be created once and re-used for many blit() calls.
88 */
89 struct blit_state *
90 util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
91 {
92 struct blit_state *ctx;
93 uint i;
94
95 ctx = CALLOC_STRUCT(blit_state);
96 if (!ctx)
97 return NULL;
98
99 ctx->pipe = pipe;
100 ctx->cso = cso;
101
102 /* disabled blending/masking */
103 ctx->blend_write_color.rt[0].colormask = PIPE_MASK_RGBA;
104
105 /* depth stencil states */
106 ctx->dsa_write_depth.depth.enabled = 1;
107 ctx->dsa_write_depth.depth.writemask = 1;
108 ctx->dsa_write_depth.depth.func = PIPE_FUNC_ALWAYS;
109 ctx->dsa_write_stencil.stencil[0].enabled = 1;
110 ctx->dsa_write_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
111 ctx->dsa_write_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
112 ctx->dsa_write_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
113 ctx->dsa_write_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
114 ctx->dsa_write_stencil.stencil[0].valuemask = 0xff;
115 ctx->dsa_write_stencil.stencil[0].writemask = 0xff;
116 ctx->dsa_write_depthstencil.depth = ctx->dsa_write_depth.depth;
117 ctx->dsa_write_depthstencil.stencil[0] = ctx->dsa_write_stencil.stencil[0];
118
119 /* rasterizer */
120 ctx->rasterizer.cull_face = PIPE_FACE_NONE;
121 ctx->rasterizer.half_pixel_center = 1;
122 ctx->rasterizer.bottom_edge_rule = 1;
123 ctx->rasterizer.depth_clip = 1;
124
125 /* samplers */
126 ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
127 ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
128 ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
129 ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
130 ctx->sampler.min_img_filter = 0; /* set later */
131 ctx->sampler.mag_img_filter = 0; /* set later */
132
133 /* vertex elements state */
134 for (i = 0; i < 2; i++) {
135 ctx->velem[i].src_offset = i * 4 * sizeof(float);
136 ctx->velem[i].instance_divisor = 0;
137 ctx->velem[i].vertex_buffer_index = cso_get_aux_vertex_buffer_slot(cso);
138 ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
139 }
140
141 ctx->vbuf = NULL;
142
143 /* init vertex data that doesn't change */
144 for (i = 0; i < 4; i++) {
145 ctx->vertices[i][0][3] = 1.0f; /* w */
146 ctx->vertices[i][1][2] = 0.0f; /* r */
147 ctx->vertices[i][1][3] = 1.0f; /* q */
148 }
149
150 if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
151 ctx->internal_target = PIPE_TEXTURE_2D;
152 else
153 ctx->internal_target = PIPE_TEXTURE_RECT;
154
155 ctx->has_stencil_export =
156 pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT);
157
158 return ctx;
159 }
160
161
162 /**
163 * Destroy a blit context
164 */
165 void
166 util_destroy_blit(struct blit_state *ctx)
167 {
168 struct pipe_context *pipe = ctx->pipe;
169 unsigned i, j;
170
171 if (ctx->vs)
172 pipe->delete_vs_state(pipe, ctx->vs);
173
174 for (i = 0; i < Elements(ctx->fs); i++) {
175 for (j = 0; j < Elements(ctx->fs[i]); j++) {
176 if (ctx->fs[i][j])
177 pipe->delete_fs_state(pipe, ctx->fs[i][j]);
178 }
179 }
180
181 for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) {
182 if (ctx->fs_depthstencil[i]) {
183 pipe->delete_fs_state(pipe, ctx->fs_depthstencil[i]);
184 }
185 if (ctx->fs_depth[i]) {
186 pipe->delete_fs_state(pipe, ctx->fs_depth[i]);
187 }
188 if (ctx->fs_stencil[i]) {
189 pipe->delete_fs_state(pipe, ctx->fs_stencil[i]);
190 }
191 }
192
193 pipe_resource_reference(&ctx->vbuf, NULL);
194
195 FREE(ctx);
196 }
197
198
199 /**
200 * Helper function to set the fragment shaders.
201 */
202 static INLINE void
203 set_fragment_shader(struct blit_state *ctx, uint writemask,
204 enum pipe_texture_target pipe_tex)
205 {
206 if (!ctx->fs[pipe_tex][writemask]) {
207 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
208
209 ctx->fs[pipe_tex][writemask] =
210 util_make_fragment_tex_shader_writemask(ctx->pipe, tgsi_tex,
211 TGSI_INTERPOLATE_LINEAR,
212 writemask);
213 }
214
215 cso_set_fragment_shader_handle(ctx->cso, ctx->fs[pipe_tex][writemask]);
216 }
217
218
219 /**
220 * Helper function to set the shader which writes depth and stencil.
221 */
222 static INLINE void
223 set_depthstencil_fragment_shader(struct blit_state *ctx,
224 enum pipe_texture_target pipe_tex)
225 {
226 if (!ctx->fs_depthstencil[pipe_tex]) {
227 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
228
229 ctx->fs_depthstencil[pipe_tex] =
230 util_make_fragment_tex_shader_writedepthstencil(ctx->pipe, tgsi_tex,
231 TGSI_INTERPOLATE_LINEAR);
232 }
233
234 cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depthstencil[pipe_tex]);
235 }
236
237
238 /**
239 * Helper function to set the shader which writes depth.
240 */
241 static INLINE void
242 set_depth_fragment_shader(struct blit_state *ctx,
243 enum pipe_texture_target pipe_tex)
244 {
245 if (!ctx->fs_depth[pipe_tex]) {
246 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
247
248 ctx->fs_depth[pipe_tex] =
249 util_make_fragment_tex_shader_writedepth(ctx->pipe, tgsi_tex,
250 TGSI_INTERPOLATE_LINEAR);
251 }
252
253 cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth[pipe_tex]);
254 }
255
256
257 /**
258 * Helper function to set the shader which writes stencil.
259 */
260 static INLINE void
261 set_stencil_fragment_shader(struct blit_state *ctx,
262 enum pipe_texture_target pipe_tex)
263 {
264 if (!ctx->fs_stencil[pipe_tex]) {
265 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
266
267 ctx->fs_stencil[pipe_tex] =
268 util_make_fragment_tex_shader_writestencil(ctx->pipe, tgsi_tex,
269 TGSI_INTERPOLATE_LINEAR);
270 }
271
272 cso_set_fragment_shader_handle(ctx->cso, ctx->fs_stencil[pipe_tex]);
273 }
274
275
276 /**
277 * Helper function to set the vertex shader.
278 */
279 static INLINE void
280 set_vertex_shader(struct blit_state *ctx)
281 {
282 /* vertex shader - still required to provide the linkage between
283 * fragment shader input semantics and vertex_element/buffers.
284 */
285 if (!ctx->vs) {
286 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
287 TGSI_SEMANTIC_GENERIC };
288 const uint semantic_indexes[] = { 0, 0 };
289 ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2,
290 semantic_names,
291 semantic_indexes);
292 }
293
294 cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
295 }
296
297
298 /**
299 * Get offset of next free slot in vertex buffer for quad vertices.
300 */
301 static unsigned
302 get_next_slot( struct blit_state *ctx )
303 {
304 const unsigned max_slots = 4096 / sizeof ctx->vertices;
305
306 if (ctx->vbuf_slot >= max_slots) {
307 pipe_resource_reference(&ctx->vbuf, NULL);
308 ctx->vbuf_slot = 0;
309 }
310
311 if (!ctx->vbuf) {
312 ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
313 PIPE_BIND_VERTEX_BUFFER,
314 PIPE_USAGE_STREAM,
315 max_slots * sizeof ctx->vertices);
316 }
317
318 return ctx->vbuf_slot++ * sizeof ctx->vertices;
319 }
320
321
322
323
324 /**
325 * Setup vertex data for the textured quad we'll draw.
326 * Note: y=0=top
327 */
328 static unsigned
329 setup_vertex_data_tex(struct blit_state *ctx,
330 float x0, float y0, float x1, float y1,
331 float s0, float t0, float s1, float t1,
332 float z)
333 {
334 unsigned offset;
335
336 ctx->vertices[0][0][0] = x0;
337 ctx->vertices[0][0][1] = y0;
338 ctx->vertices[0][0][2] = z;
339 ctx->vertices[0][1][0] = s0; /*s*/
340 ctx->vertices[0][1][1] = t0; /*t*/
341
342 ctx->vertices[1][0][0] = x1;
343 ctx->vertices[1][0][1] = y0;
344 ctx->vertices[1][0][2] = z;
345 ctx->vertices[1][1][0] = s1; /*s*/
346 ctx->vertices[1][1][1] = t0; /*t*/
347
348 ctx->vertices[2][0][0] = x1;
349 ctx->vertices[2][0][1] = y1;
350 ctx->vertices[2][0][2] = z;
351 ctx->vertices[2][1][0] = s1;
352 ctx->vertices[2][1][1] = t1;
353
354 ctx->vertices[3][0][0] = x0;
355 ctx->vertices[3][0][1] = y1;
356 ctx->vertices[3][0][2] = z;
357 ctx->vertices[3][1][0] = s0;
358 ctx->vertices[3][1][1] = t1;
359
360 offset = get_next_slot( ctx );
361
362 if (ctx->vbuf) {
363 pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf,
364 offset, sizeof(ctx->vertices), ctx->vertices);
365 }
366
367 return offset;
368 }
369
370
371 /**
372 * \return TRUE if two regions overlap, FALSE otherwise
373 */
374 static boolean
375 regions_overlap(int srcX0, int srcY0,
376 int srcX1, int srcY1,
377 int dstX0, int dstY0,
378 int dstX1, int dstY1)
379 {
380 if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1))
381 return FALSE; /* src completely left of dst */
382
383 if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1))
384 return FALSE; /* dst completely left of src */
385
386 if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1))
387 return FALSE; /* src completely above dst */
388
389 if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1))
390 return FALSE; /* dst completely above src */
391
392 return TRUE; /* some overlap */
393 }
394
395
396 /**
397 * Can we blit from src format to dest format with a simple copy?
398 */
399 static boolean
400 formats_compatible(enum pipe_format src_format,
401 enum pipe_format dst_format)
402 {
403 if (src_format == dst_format) {
404 return TRUE;
405 }
406 else {
407 const struct util_format_description *src_desc =
408 util_format_description(src_format);
409 const struct util_format_description *dst_desc =
410 util_format_description(dst_format);
411 return util_is_format_compatible(src_desc, dst_desc);
412 }
413 }
414
415
416 /**
417 * Copy pixel block from src surface to dst surface.
418 * Overlapping regions are acceptable.
419 * Flipping and stretching are supported.
420 * \param filter one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR
421 * \param writemask controls which channels in the dest surface are sourced
422 * from the src surface. Disabled channels are sourced
423 * from (0,0,0,1).
424 */
425 void
426 util_blit_pixels(struct blit_state *ctx,
427 struct pipe_resource *src_tex,
428 unsigned src_level,
429 int srcX0, int srcY0,
430 int srcX1, int srcY1,
431 int srcZ0,
432 struct pipe_surface *dst,
433 int dstX0, int dstY0,
434 int dstX1, int dstY1,
435 float z, uint filter,
436 uint writemask, uint zs_writemask)
437 {
438 struct pipe_context *pipe = ctx->pipe;
439 struct pipe_screen *screen = pipe->screen;
440 enum pipe_format src_format, dst_format;
441 struct pipe_sampler_view *sampler_view = NULL;
442 struct pipe_sampler_view sv_templ;
443 struct pipe_surface *dst_surface;
444 struct pipe_framebuffer_state fb;
445 const int srcW = abs(srcX1 - srcX0);
446 const int srcH = abs(srcY1 - srcY0);
447 unsigned offset;
448 boolean overlap;
449 float s0, t0, s1, t1;
450 boolean normalized;
451 boolean is_stencil, is_depth, blit_depth, blit_stencil;
452 const struct util_format_description *src_desc =
453 util_format_description(src_tex->format);
454
455 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
456 filter == PIPE_TEX_MIPFILTER_LINEAR);
457
458 assert(src_level <= src_tex->last_level);
459
460 /* do the regions overlap? */
461 overlap = src_tex == dst->texture &&
462 dst->u.tex.level == src_level &&
463 dst->u.tex.first_layer == srcZ0 &&
464 regions_overlap(srcX0, srcY0, srcX1, srcY1,
465 dstX0, dstY0, dstX1, dstY1);
466
467 src_format = util_format_linear(src_tex->format);
468 dst_format = util_format_linear(dst->texture->format);
469
470 /* See whether we will blit depth or stencil. */
471 is_depth = util_format_has_depth(src_desc);
472 is_stencil = util_format_has_stencil(src_desc);
473
474 blit_depth = is_depth && (zs_writemask & BLIT_WRITEMASK_Z);
475 blit_stencil = is_stencil && (zs_writemask & BLIT_WRITEMASK_STENCIL);
476
477 assert((writemask && !zs_writemask && !is_depth && !is_stencil) ||
478 (!writemask && (blit_depth || blit_stencil)));
479
480 /*
481 * Check for simple case: no format conversion, no flipping, no stretching,
482 * no overlapping, same number of samples.
483 * Filter mode should not matter since there's no stretching.
484 */
485 if (formats_compatible(src_format, dst_format) &&
486 src_tex->nr_samples == dst->texture->nr_samples &&
487 is_stencil == blit_stencil &&
488 is_depth == blit_depth &&
489 srcX0 < srcX1 &&
490 dstX0 < dstX1 &&
491 srcY0 < srcY1 &&
492 dstY0 < dstY1 &&
493 (dstX1 - dstX0) == (srcX1 - srcX0) &&
494 (dstY1 - dstY0) == (srcY1 - srcY0) &&
495 !overlap) {
496 struct pipe_box src_box;
497 src_box.x = srcX0;
498 src_box.y = srcY0;
499 src_box.z = srcZ0;
500 src_box.width = srcW;
501 src_box.height = srcH;
502 src_box.depth = 1;
503 pipe->resource_copy_region(pipe,
504 dst->texture, dst->u.tex.level,
505 dstX0, dstY0, dst->u.tex.first_layer,/* dest */
506 src_tex, src_level,
507 &src_box);
508 return;
509 }
510
511 /* XXX Reading multisample textures is unimplemented. */
512 assert(src_tex->nr_samples <= 1);
513 if (src_tex->nr_samples > 1) {
514 return;
515 }
516
517 /* It's a mistake to call this function with a stencil format and
518 * without shader stencil export. We don't do software fallbacks here.
519 * Ignore stencil and only copy depth.
520 */
521 if (blit_stencil && !ctx->has_stencil_export) {
522 blit_stencil = FALSE;
523
524 if (!blit_depth)
525 return;
526 }
527
528 if (dst_format == dst->format) {
529 dst_surface = dst;
530 } else {
531 struct pipe_surface templ = *dst;
532 templ.format = dst_format;
533 dst_surface = pipe->create_surface(pipe, dst->texture, &templ);
534 }
535
536 /* Create a temporary texture when src and dest alias.
537 */
538 if (src_tex == dst_surface->texture &&
539 dst_surface->u.tex.level == src_level &&
540 dst_surface->u.tex.first_layer == srcZ0) {
541 /* Make a temporary texture which contains a copy of the source pixels.
542 * Then we'll sample from the temporary texture.
543 */
544 struct pipe_resource texTemp;
545 struct pipe_resource *tex;
546 struct pipe_sampler_view sv_templ;
547 struct pipe_box src_box;
548 const int srcLeft = MIN2(srcX0, srcX1);
549 const int srcTop = MIN2(srcY0, srcY1);
550
551 if (srcLeft != srcX0) {
552 /* left-right flip */
553 int tmp = dstX0;
554 dstX0 = dstX1;
555 dstX1 = tmp;
556 }
557
558 if (srcTop != srcY0) {
559 /* up-down flip */
560 int tmp = dstY0;
561 dstY0 = dstY1;
562 dstY1 = tmp;
563 }
564
565 /* create temp texture */
566 memset(&texTemp, 0, sizeof(texTemp));
567 texTemp.target = ctx->internal_target;
568 texTemp.format = src_format;
569 texTemp.last_level = 0;
570 texTemp.width0 = srcW;
571 texTemp.height0 = srcH;
572 texTemp.depth0 = 1;
573 texTemp.array_size = 1;
574 texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
575
576 tex = screen->resource_create(screen, &texTemp);
577 if (!tex)
578 return;
579
580 src_box.x = srcLeft;
581 src_box.y = srcTop;
582 src_box.z = srcZ0;
583 src_box.width = srcW;
584 src_box.height = srcH;
585 src_box.depth = 1;
586 /* load temp texture */
587 pipe->resource_copy_region(pipe,
588 tex, 0, 0, 0, 0, /* dest */
589 src_tex, src_level, &src_box);
590
591 normalized = tex->target != PIPE_TEXTURE_RECT;
592 if(normalized) {
593 s0 = 0.0f;
594 s1 = 1.0f;
595 t0 = 0.0f;
596 t1 = 1.0f;
597 }
598 else {
599 s0 = 0.0f;
600 s1 = (float) srcW;
601 t0 = 0.0f;
602 t1 = (float) srcH;
603 }
604
605 u_sampler_view_default_template(&sv_templ, tex, tex->format);
606 if (!blit_depth && blit_stencil) {
607 /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
608 sv_templ.format = util_format_stencil_only(tex->format);
609 assert(sv_templ.format != PIPE_FORMAT_NONE);
610 }
611 sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ);
612
613 if (!sampler_view) {
614 pipe_resource_reference(&tex, NULL);
615 return;
616 }
617 pipe_resource_reference(&tex, NULL);
618 }
619 else {
620 /* Directly sample from the source resource/texture */
621 u_sampler_view_default_template(&sv_templ, src_tex, src_format);
622 if (!blit_depth && blit_stencil) {
623 /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
624 sv_templ.format = util_format_stencil_only(src_format);
625 assert(sv_templ.format != PIPE_FORMAT_NONE);
626 }
627 sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);
628
629 if (!sampler_view) {
630 return;
631 }
632
633 s0 = (float) srcX0;
634 s1 = (float) srcX1;
635 t0 = (float) srcY0;
636 t1 = (float) srcY1;
637 normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT;
638 if(normalized)
639 {
640 s0 /= (float)(u_minify(sampler_view->texture->width0, src_level));
641 s1 /= (float)(u_minify(sampler_view->texture->width0, src_level));
642 t0 /= (float)(u_minify(sampler_view->texture->height0, src_level));
643 t1 /= (float)(u_minify(sampler_view->texture->height0, src_level));
644 }
645 }
646
647 assert(screen->is_format_supported(screen, sampler_view->format,
648 ctx->internal_target, sampler_view->texture->nr_samples,
649 PIPE_BIND_SAMPLER_VIEW));
650 assert(screen->is_format_supported(screen, dst_format, ctx->internal_target,
651 dst_surface->texture->nr_samples,
652 is_depth || is_stencil ? PIPE_BIND_DEPTH_STENCIL :
653 PIPE_BIND_RENDER_TARGET));
654
655 /* save state (restored below) */
656 cso_save_blend(ctx->cso);
657 cso_save_depth_stencil_alpha(ctx->cso);
658 cso_save_rasterizer(ctx->cso);
659 cso_save_sample_mask(ctx->cso);
660 cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
661 cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
662 cso_save_stream_outputs(ctx->cso);
663 cso_save_viewport(ctx->cso);
664 cso_save_framebuffer(ctx->cso);
665 cso_save_fragment_shader(ctx->cso);
666 cso_save_vertex_shader(ctx->cso);
667 cso_save_geometry_shader(ctx->cso);
668 cso_save_vertex_elements(ctx->cso);
669 cso_save_aux_vertex_buffer_slot(ctx->cso);
670 cso_save_render_condition(ctx->cso);
671
672 /* set misc state we care about */
673 if (writemask)
674 cso_set_blend(ctx->cso, &ctx->blend_write_color);
675 else
676 cso_set_blend(ctx->cso, &ctx->blend_keep_color);
677
678 cso_set_sample_mask(ctx->cso, ~0);
679 cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
680 cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
681 cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
682 cso_set_render_condition(ctx->cso, NULL, FALSE, 0);
683
684 /* default sampler state */
685 ctx->sampler.normalized_coords = normalized;
686 ctx->sampler.min_img_filter = filter;
687 ctx->sampler.mag_img_filter = filter;
688 ctx->sampler.min_lod = (float) src_level;
689 ctx->sampler.max_lod = (float) src_level;
690
691 /* Depth stencil state, fragment shader and sampler setup depending on what
692 * we blit.
693 */
694 if (blit_depth && blit_stencil) {
695 cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
696 /* don't filter stencil */
697 ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
698 ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
699 cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &ctx->sampler);
700
701 cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depthstencil);
702 set_depthstencil_fragment_shader(ctx, sampler_view->texture->target);
703 }
704 else if (blit_depth) {
705 cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
706 cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depth);
707 set_depth_fragment_shader(ctx, sampler_view->texture->target);
708 }
709 else if (blit_stencil) {
710 /* don't filter stencil */
711 ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
712 ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
713 cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
714
715 cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_stencil);
716 set_stencil_fragment_shader(ctx, sampler_view->texture->target);
717 }
718 else { /* color */
719 cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
720 cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
721 set_fragment_shader(ctx, writemask, sampler_view->texture->target);
722 }
723 cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);
724
725 /* textures */
726 if (blit_depth && blit_stencil) {
727 /* Setup two samplers, one for depth and the other one for stencil. */
728 struct pipe_sampler_view templ;
729 struct pipe_sampler_view *views[2];
730
731 templ = *sampler_view;
732 templ.format = util_format_stencil_only(templ.format);
733 assert(templ.format != PIPE_FORMAT_NONE);
734
735 views[0] = sampler_view;
736 views[1] = pipe->create_sampler_view(pipe, views[0]->texture, &templ);
737 cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 2, views);
738
739 pipe_sampler_view_reference(&views[1], NULL);
740 }
741 else {
742 cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &sampler_view);
743 }
744
745 /* viewport */
746 ctx->viewport.scale[0] = 0.5f * dst_surface->width;
747 ctx->viewport.scale[1] = 0.5f * dst_surface->height;
748 ctx->viewport.scale[2] = 0.5f;
749 ctx->viewport.scale[3] = 1.0f;
750 ctx->viewport.translate[0] = 0.5f * dst_surface->width;
751 ctx->viewport.translate[1] = 0.5f * dst_surface->height;
752 ctx->viewport.translate[2] = 0.5f;
753 ctx->viewport.translate[3] = 0.0f;
754 cso_set_viewport(ctx->cso, &ctx->viewport);
755
756 set_vertex_shader(ctx);
757 cso_set_geometry_shader_handle(ctx->cso, NULL);
758
759 /* drawing dest */
760 memset(&fb, 0, sizeof(fb));
761 fb.width = dst_surface->width;
762 fb.height = dst_surface->height;
763 if (blit_depth || blit_stencil) {
764 fb.zsbuf = dst_surface;
765 } else {
766 fb.nr_cbufs = 1;
767 fb.cbufs[0] = dst_surface;
768 }
769 cso_set_framebuffer(ctx->cso, &fb);
770
771 /* draw quad */
772 offset = setup_vertex_data_tex(ctx,
773 (float) dstX0 / dst_surface->width * 2.0f - 1.0f,
774 (float) dstY0 / dst_surface->height * 2.0f - 1.0f,
775 (float) dstX1 / dst_surface->width * 2.0f - 1.0f,
776 (float) dstY1 / dst_surface->height * 2.0f - 1.0f,
777 s0, t0,
778 s1, t1,
779 z);
780
781 if (ctx->vbuf) {
782 util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf,
783 cso_get_aux_vertex_buffer_slot(ctx->cso),
784 offset,
785 PIPE_PRIM_TRIANGLE_FAN,
786 4, /* verts */
787 2); /* attribs/vert */
788 }
789
790 /* restore state we changed */
791 cso_restore_blend(ctx->cso);
792 cso_restore_depth_stencil_alpha(ctx->cso);
793 cso_restore_rasterizer(ctx->cso);
794 cso_restore_sample_mask(ctx->cso);
795 cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
796 cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
797 cso_restore_viewport(ctx->cso);
798 cso_restore_framebuffer(ctx->cso);
799 cso_restore_fragment_shader(ctx->cso);
800 cso_restore_vertex_shader(ctx->cso);
801 cso_restore_geometry_shader(ctx->cso);
802 cso_restore_vertex_elements(ctx->cso);
803 cso_restore_aux_vertex_buffer_slot(ctx->cso);
804 cso_restore_stream_outputs(ctx->cso);
805 cso_restore_render_condition(ctx->cso);
806
807 pipe_sampler_view_reference(&sampler_view, NULL);
808 if (dst_surface != dst)
809 pipe_surface_reference(&dst_surface, NULL);
810 }
811
812
813 /**
814 * Copy pixel block from src texture to dst surface.
815 * The sampler view's first_level field indicates the source
816 * mipmap level to use.
817 * XXX need some control over blitting Z and/or stencil.
818 */
819 void
820 util_blit_pixels_tex(struct blit_state *ctx,
821 struct pipe_sampler_view *src_sampler_view,
822 int srcX0, int srcY0,
823 int srcX1, int srcY1,
824 struct pipe_surface *dst,
825 int dstX0, int dstY0,
826 int dstX1, int dstY1,
827 float z, uint filter)
828 {
829 boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
830 struct pipe_framebuffer_state fb;
831 float s0, t0, s1, t1;
832 unsigned offset;
833 struct pipe_resource *tex = src_sampler_view->texture;
834
835 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
836 filter == PIPE_TEX_MIPFILTER_LINEAR);
837
838 assert(tex);
839 assert(tex->width0 != 0);
840 assert(tex->height0 != 0);
841
842 s0 = (float) srcX0;
843 s1 = (float) srcX1;
844 t0 = (float) srcY0;
845 t1 = (float) srcY1;
846
847 if(normalized)
848 {
849 /* normalize according to the mipmap level's size */
850 int level = src_sampler_view->u.tex.first_level;
851 float w = (float) u_minify(tex->width0, level);
852 float h = (float) u_minify(tex->height0, level);
853 s0 /= w;
854 s1 /= w;
855 t0 /= h;
856 t1 /= h;
857 }
858
859 assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
860 PIPE_TEXTURE_2D,
861 dst->texture->nr_samples,
862 PIPE_BIND_RENDER_TARGET));
863
864 /* save state (restored below) */
865 cso_save_blend(ctx->cso);
866 cso_save_depth_stencil_alpha(ctx->cso);
867 cso_save_rasterizer(ctx->cso);
868 cso_save_sample_mask(ctx->cso);
869 cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
870 cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
871 cso_save_stream_outputs(ctx->cso);
872 cso_save_viewport(ctx->cso);
873 cso_save_framebuffer(ctx->cso);
874 cso_save_fragment_shader(ctx->cso);
875 cso_save_vertex_shader(ctx->cso);
876 cso_save_geometry_shader(ctx->cso);
877 cso_save_vertex_elements(ctx->cso);
878 cso_save_aux_vertex_buffer_slot(ctx->cso);
879
880 /* set misc state we care about */
881 cso_set_blend(ctx->cso, &ctx->blend_write_color);
882 cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
883 cso_set_sample_mask(ctx->cso, ~0);
884 cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
885 cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
886 cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
887
888 /* sampler */
889 ctx->sampler.normalized_coords = normalized;
890 ctx->sampler.min_img_filter = filter;
891 ctx->sampler.mag_img_filter = filter;
892 cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
893 cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);
894
895 /* viewport */
896 ctx->viewport.scale[0] = 0.5f * dst->width;
897 ctx->viewport.scale[1] = 0.5f * dst->height;
898 ctx->viewport.scale[2] = 0.5f;
899 ctx->viewport.scale[3] = 1.0f;
900 ctx->viewport.translate[0] = 0.5f * dst->width;
901 ctx->viewport.translate[1] = 0.5f * dst->height;
902 ctx->viewport.translate[2] = 0.5f;
903 ctx->viewport.translate[3] = 0.0f;
904 cso_set_viewport(ctx->cso, &ctx->viewport);
905
906 /* texture */
907 cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &src_sampler_view);
908
909 /* shaders */
910 set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW,
911 src_sampler_view->texture->target);
912 set_vertex_shader(ctx);
913 cso_set_geometry_shader_handle(ctx->cso, NULL);
914
915 /* drawing dest */
916 memset(&fb, 0, sizeof(fb));
917 fb.width = dst->width;
918 fb.height = dst->height;
919 fb.nr_cbufs = 1;
920 fb.cbufs[0] = dst;
921 cso_set_framebuffer(ctx->cso, &fb);
922
923 /* draw quad */
924 offset = setup_vertex_data_tex(ctx,
925 (float) dstX0 / dst->width * 2.0f - 1.0f,
926 (float) dstY0 / dst->height * 2.0f - 1.0f,
927 (float) dstX1 / dst->width * 2.0f - 1.0f,
928 (float) dstY1 / dst->height * 2.0f - 1.0f,
929 s0, t0, s1, t1,
930 z);
931
932 util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf,
933 cso_get_aux_vertex_buffer_slot(ctx->cso),
934 offset,
935 PIPE_PRIM_TRIANGLE_FAN,
936 4, /* verts */
937 2); /* attribs/vert */
938
939 /* restore state we changed */
940 cso_restore_blend(ctx->cso);
941 cso_restore_depth_stencil_alpha(ctx->cso);
942 cso_restore_rasterizer(ctx->cso);
943 cso_restore_sample_mask(ctx->cso);
944 cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
945 cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
946 cso_restore_viewport(ctx->cso);
947 cso_restore_framebuffer(ctx->cso);
948 cso_restore_fragment_shader(ctx->cso);
949 cso_restore_vertex_shader(ctx->cso);
950 cso_restore_geometry_shader(ctx->cso);
951 cso_restore_vertex_elements(ctx->cso);
952 cso_restore_aux_vertex_buffer_slot(ctx->cso);
953 cso_restore_stream_outputs(ctx->cso);
954 }