Merge remote branch 'origin/master' into pipe-video
[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;
60 struct pipe_depth_stencil_alpha_state depthstencil_keep;
61 struct pipe_depth_stencil_alpha_state depthstencil_write;
62 struct pipe_rasterizer_state rasterizer;
63 struct pipe_sampler_state sampler;
64 struct pipe_viewport_state viewport;
65 struct pipe_clip_state clip;
66 struct pipe_vertex_element velem[2];
67 enum pipe_texture_target internal_target;
68
69 void *vs;
70 void *fs[TGSI_WRITEMASK_XYZW + 1];
71 void *fs_depth;
72
73 struct pipe_resource *vbuf; /**< quad vertices */
74 unsigned vbuf_slot;
75
76 float vertices[4][2][4]; /**< vertex/texcoords for quad */
77 };
78
79
80 /**
81 * Create state object for blit.
82 * Intended to be created once and re-used for many blit() calls.
83 */
84 struct blit_state *
85 util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
86 {
87 struct blit_state *ctx;
88 uint i;
89
90 ctx = CALLOC_STRUCT(blit_state);
91 if (!ctx)
92 return NULL;
93
94 ctx->pipe = pipe;
95 ctx->cso = cso;
96
97 /* disabled blending/masking */
98 memset(&ctx->blend, 0, sizeof(ctx->blend));
99 ctx->blend.rt[0].colormask = PIPE_MASK_RGBA;
100
101 /* no-op depth/stencil/alpha */
102 memset(&ctx->depthstencil_keep, 0, sizeof(ctx->depthstencil_keep));
103 memset(&ctx->depthstencil_write, 0, sizeof(ctx->depthstencil_write));
104 ctx->depthstencil_write.depth.enabled = 1;
105 ctx->depthstencil_write.depth.writemask = 1;
106 ctx->depthstencil_write.depth.func = PIPE_FUNC_ALWAYS;
107
108 /* rasterizer */
109 memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
110 ctx->rasterizer.cull_face = PIPE_FACE_NONE;
111 ctx->rasterizer.gl_rasterization_rules = 1;
112
113 /* samplers */
114 memset(&ctx->sampler, 0, sizeof(ctx->sampler));
115 ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
116 ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
117 ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
118 ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
119 ctx->sampler.min_img_filter = 0; /* set later */
120 ctx->sampler.mag_img_filter = 0; /* set later */
121
122 /* vertex elements state */
123 memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2);
124 for (i = 0; i < 2; i++) {
125 ctx->velem[i].src_offset = i * 4 * sizeof(float);
126 ctx->velem[i].instance_divisor = 0;
127 ctx->velem[i].vertex_buffer_index = 0;
128 ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
129 }
130
131 ctx->vbuf = NULL;
132
133 /* init vertex data that doesn't change */
134 for (i = 0; i < 4; i++) {
135 ctx->vertices[i][0][3] = 1.0f; /* w */
136 ctx->vertices[i][1][2] = 0.0f; /* r */
137 ctx->vertices[i][1][3] = 1.0f; /* q */
138 }
139
140 if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
141 ctx->internal_target = PIPE_TEXTURE_2D;
142 else
143 ctx->internal_target = PIPE_TEXTURE_RECT;
144
145 return ctx;
146 }
147
148
149 /**
150 * Destroy a blit context
151 */
152 void
153 util_destroy_blit(struct blit_state *ctx)
154 {
155 struct pipe_context *pipe = ctx->pipe;
156 unsigned i;
157
158 if (ctx->vs)
159 pipe->delete_vs_state(pipe, ctx->vs);
160
161 for (i = 0; i < Elements(ctx->fs); i++)
162 if (ctx->fs[i])
163 pipe->delete_fs_state(pipe, ctx->fs[i]);
164
165 if (ctx->fs_depth)
166 pipe->delete_fs_state(pipe, ctx->fs_depth);
167
168 pipe_resource_reference(&ctx->vbuf, NULL);
169
170 FREE(ctx);
171 }
172
173
174 /**
175 * Helper function to set the fragment shaders.
176 */
177 static INLINE void
178 set_fragment_shader(struct blit_state *ctx, uint writemask)
179 {
180 if (!ctx->fs[writemask])
181 ctx->fs[writemask] =
182 util_make_fragment_tex_shader_writemask(ctx->pipe, TGSI_TEXTURE_2D,
183 TGSI_INTERPOLATE_LINEAR,
184 writemask);
185
186 cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]);
187 }
188
189
190 /**
191 * Helper function to set the depthwrite shader.
192 */
193 static INLINE void
194 set_depth_fragment_shader(struct blit_state *ctx)
195 {
196 if (!ctx->fs_depth)
197 ctx->fs_depth =
198 util_make_fragment_tex_shader_writedepth(ctx->pipe, TGSI_TEXTURE_2D,
199 TGSI_INTERPOLATE_LINEAR);
200
201 cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth);
202 }
203
204
205 /**
206 * Helper function to set the vertex shader.
207 */
208 static INLINE void
209 set_vertex_shader(struct blit_state *ctx)
210 {
211 /* vertex shader - still required to provide the linkage between
212 * fragment shader input semantics and vertex_element/buffers.
213 */
214 if (!ctx->vs) {
215 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
216 TGSI_SEMANTIC_GENERIC };
217 const uint semantic_indexes[] = { 0, 0 };
218 ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2,
219 semantic_names,
220 semantic_indexes);
221 }
222
223 cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
224 }
225
226
227 /**
228 * Get offset of next free slot in vertex buffer for quad vertices.
229 */
230 static unsigned
231 get_next_slot( struct blit_state *ctx )
232 {
233 const unsigned max_slots = 4096 / sizeof ctx->vertices;
234
235 if (ctx->vbuf_slot >= max_slots)
236 util_blit_flush( ctx );
237
238 if (!ctx->vbuf) {
239 ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
240 PIPE_BIND_VERTEX_BUFFER,
241 PIPE_USAGE_STREAM,
242 max_slots * sizeof ctx->vertices);
243 }
244
245 return ctx->vbuf_slot++ * sizeof ctx->vertices;
246 }
247
248
249
250
251 /**
252 * Setup vertex data for the textured quad we'll draw.
253 * Note: y=0=top
254 */
255 static unsigned
256 setup_vertex_data_tex(struct blit_state *ctx,
257 float x0, float y0, float x1, float y1,
258 float s0, float t0, float s1, float t1,
259 float z)
260 {
261 unsigned offset;
262
263 ctx->vertices[0][0][0] = x0;
264 ctx->vertices[0][0][1] = y0;
265 ctx->vertices[0][0][2] = z;
266 ctx->vertices[0][1][0] = s0; /*s*/
267 ctx->vertices[0][1][1] = t0; /*t*/
268
269 ctx->vertices[1][0][0] = x1;
270 ctx->vertices[1][0][1] = y0;
271 ctx->vertices[1][0][2] = z;
272 ctx->vertices[1][1][0] = s1; /*s*/
273 ctx->vertices[1][1][1] = t0; /*t*/
274
275 ctx->vertices[2][0][0] = x1;
276 ctx->vertices[2][0][1] = y1;
277 ctx->vertices[2][0][2] = z;
278 ctx->vertices[2][1][0] = s1;
279 ctx->vertices[2][1][1] = t1;
280
281 ctx->vertices[3][0][0] = x0;
282 ctx->vertices[3][0][1] = y1;
283 ctx->vertices[3][0][2] = z;
284 ctx->vertices[3][1][0] = s0;
285 ctx->vertices[3][1][1] = t1;
286
287 offset = get_next_slot( ctx );
288
289 pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf,
290 offset, sizeof(ctx->vertices), ctx->vertices);
291
292 return offset;
293 }
294
295
296 /**
297 * \return TRUE if two regions overlap, FALSE otherwise
298 */
299 static boolean
300 regions_overlap(int srcX0, int srcY0,
301 int srcX1, int srcY1,
302 int dstX0, int dstY0,
303 int dstX1, int dstY1)
304 {
305 if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1))
306 return FALSE; /* src completely left of dst */
307
308 if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1))
309 return FALSE; /* dst completely left of src */
310
311 if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1))
312 return FALSE; /* src completely above dst */
313
314 if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1))
315 return FALSE; /* dst completely above src */
316
317 return TRUE; /* some overlap */
318 }
319
320
321 /**
322 * Copy pixel block from src surface to dst surface.
323 * Overlapping regions are acceptable.
324 * Flipping and stretching are supported.
325 * \param filter one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR
326 * \param writemask controls which channels in the dest surface are sourced
327 * from the src surface. Disabled channels are sourced
328 * from (0,0,0,1).
329 * XXX need some control over blitting stencil.
330 */
331 void
332 util_blit_pixels_writemask(struct blit_state *ctx,
333 struct pipe_resource *src_tex,
334 unsigned src_level,
335 int srcX0, int srcY0,
336 int srcX1, int srcY1,
337 int srcZ0,
338 struct pipe_surface *dst,
339 int dstX0, int dstY0,
340 int dstX1, int dstY1,
341 float z, uint filter,
342 uint writemask)
343 {
344 struct pipe_context *pipe = ctx->pipe;
345 struct pipe_screen *screen = pipe->screen;
346 enum pipe_format src_format, dst_format;
347 struct pipe_sampler_view *sampler_view = NULL;
348 struct pipe_sampler_view sv_templ;
349 struct pipe_surface *dst_surface;
350 struct pipe_framebuffer_state fb;
351 const int srcW = abs(srcX1 - srcX0);
352 const int srcH = abs(srcY1 - srcY0);
353 unsigned offset;
354 boolean overlap, dst_is_depth;
355 float s0, t0, s1, t1;
356 boolean normalized;
357
358 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
359 filter == PIPE_TEX_MIPFILTER_LINEAR);
360
361 assert(src_level <= src_tex->last_level);
362
363 /* do the regions overlap? */
364 overlap = src_tex == dst->texture &&
365 dst->u.tex.level == src_level &&
366 dst->u.tex.first_layer == srcZ0 &&
367 regions_overlap(srcX0, srcY0, srcX1, srcY1,
368 dstX0, dstY0, dstX1, dstY1);
369
370 src_format = util_format_linear(src_tex->format);
371 dst_format = util_format_linear(dst->format);
372
373 /*
374 * Check for simple case: no format conversion, no flipping, no stretching,
375 * no overlapping.
376 * Filter mode should not matter since there's no stretching.
377 */
378 if (dst_format == src_format &&
379 srcX0 < srcX1 &&
380 dstX0 < dstX1 &&
381 srcY0 < srcY1 &&
382 dstY0 < dstY1 &&
383 (dstX1 - dstX0) == (srcX1 - srcX0) &&
384 (dstY1 - dstY0) == (srcY1 - srcY0) &&
385 !overlap) {
386 struct pipe_box src_box;
387 src_box.x = srcX0;
388 src_box.y = srcY0;
389 src_box.z = srcZ0;
390 src_box.width = srcW;
391 src_box.height = srcH;
392 src_box.depth = 1;
393 pipe->resource_copy_region(pipe,
394 dst->texture, dst->u.tex.level,
395 dstX0, dstY0, dst->u.tex.first_layer,/* dest */
396 src_tex, src_level,
397 &src_box);
398 return;
399 }
400
401 if (dst_format == dst->format) {
402 dst_surface = dst;
403 } else {
404 struct pipe_surface templ = *dst;
405 templ.format = dst_format;
406 dst_surface = pipe->create_surface(pipe, dst->texture, &templ);
407 }
408
409 /* Create a temporary texture when src and dest alias or when src
410 * is anything other than a 2d texture.
411 * XXX should just use appropriate shader to access 1d / 3d slice / cube face,
412 * much like the u_blitter code does (should be pretty trivial).
413 *
414 * This can still be improved upon.
415 */
416 if ((src_tex == dst_surface->texture &&
417 dst_surface->u.tex.level == src_level &&
418 dst_surface->u.tex.first_layer == srcZ0) ||
419 (src_tex->target != PIPE_TEXTURE_2D &&
420 src_tex->target != PIPE_TEXTURE_2D &&
421 src_tex->target != PIPE_TEXTURE_RECT))
422 {
423 struct pipe_resource texTemp;
424 struct pipe_resource *tex;
425 struct pipe_sampler_view sv_templ;
426 struct pipe_box src_box;
427 const int srcLeft = MIN2(srcX0, srcX1);
428 const int srcTop = MIN2(srcY0, srcY1);
429
430 if (srcLeft != srcX0) {
431 /* left-right flip */
432 int tmp = dstX0;
433 dstX0 = dstX1;
434 dstX1 = tmp;
435 }
436
437 if (srcTop != srcY0) {
438 /* up-down flip */
439 int tmp = dstY0;
440 dstY0 = dstY1;
441 dstY1 = tmp;
442 }
443
444 /* create temp texture */
445 memset(&texTemp, 0, sizeof(texTemp));
446 texTemp.target = ctx->internal_target;
447 texTemp.format = src_format;
448 texTemp.last_level = 0;
449 texTemp.width0 = srcW;
450 texTemp.height0 = srcH;
451 texTemp.depth0 = 1;
452 texTemp.array_size = 1;
453 texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
454
455 tex = screen->resource_create(screen, &texTemp);
456 if (!tex)
457 return;
458
459 src_box.x = srcLeft;
460 src_box.y = srcTop;
461 src_box.z = srcZ0;
462 src_box.width = srcW;
463 src_box.height = srcH;
464 src_box.depth = 1;
465 /* load temp texture */
466 pipe->resource_copy_region(pipe,
467 tex, 0, 0, 0, 0, /* dest */
468 src_tex, src_level, &src_box);
469
470 normalized = tex->target != PIPE_TEXTURE_RECT;
471 if(normalized) {
472 s0 = 0.0f;
473 s1 = 1.0f;
474 t0 = 0.0f;
475 t1 = 1.0f;
476 }
477 else {
478 s0 = 0;
479 s1 = srcW;
480 t0 = 0;
481 t1 = srcH;
482 }
483
484 u_sampler_view_default_template(&sv_templ, tex, tex->format);
485 sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ);
486
487 if (!sampler_view) {
488 pipe_resource_reference(&tex, NULL);
489 return;
490 }
491 pipe_resource_reference(&tex, NULL);
492 }
493 else {
494 u_sampler_view_default_template(&sv_templ, src_tex, src_format);
495 sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);
496
497 if (!sampler_view) {
498 return;
499 }
500
501 s0 = srcX0;
502 s1 = srcX1;
503 t0 = srcY0;
504 t1 = srcY1;
505 normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT;
506 if(normalized)
507 {
508 s0 /= (float)(u_minify(sampler_view->texture->width0, src_level));
509 s1 /= (float)(u_minify(sampler_view->texture->width0, src_level));
510 t0 /= (float)(u_minify(sampler_view->texture->height0, src_level));
511 t1 /= (float)(u_minify(sampler_view->texture->height0, src_level));
512 }
513 }
514
515 dst_is_depth = util_format_is_depth_or_stencil(dst_format);
516
517 assert(screen->is_format_supported(screen, sampler_view->format, ctx->internal_target,
518 sampler_view->texture->nr_samples,
519 PIPE_BIND_SAMPLER_VIEW));
520 assert(screen->is_format_supported(screen, dst_format, ctx->internal_target,
521 dst_surface->texture->nr_samples,
522 dst_is_depth ? PIPE_BIND_DEPTH_STENCIL :
523 PIPE_BIND_RENDER_TARGET));
524 /* save state (restored below) */
525 cso_save_blend(ctx->cso);
526 cso_save_depth_stencil_alpha(ctx->cso);
527 cso_save_rasterizer(ctx->cso);
528 cso_save_samplers(ctx->cso);
529 cso_save_fragment_sampler_views(ctx->cso);
530 cso_save_viewport(ctx->cso);
531 cso_save_framebuffer(ctx->cso);
532 cso_save_fragment_shader(ctx->cso);
533 cso_save_vertex_shader(ctx->cso);
534 cso_save_clip(ctx->cso);
535 cso_save_vertex_elements(ctx->cso);
536 cso_save_vertex_buffers(ctx->cso);
537
538 /* set misc state we care about */
539 cso_set_blend(ctx->cso, &ctx->blend);
540 cso_set_depth_stencil_alpha(ctx->cso,
541 dst_is_depth ? &ctx->depthstencil_write :
542 &ctx->depthstencil_keep);
543 cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
544 cso_set_clip(ctx->cso, &ctx->clip);
545 cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
546
547 /* sampler */
548 ctx->sampler.normalized_coords = normalized;
549 ctx->sampler.min_img_filter = filter;
550 ctx->sampler.mag_img_filter = filter;
551 ctx->sampler.min_lod = src_level;
552 ctx->sampler.max_lod = src_level;
553 cso_single_sampler(ctx->cso, 0, &ctx->sampler);
554 cso_single_sampler_done(ctx->cso);
555
556 /* viewport */
557 ctx->viewport.scale[0] = 0.5f * dst_surface->width;
558 ctx->viewport.scale[1] = 0.5f * dst_surface->height;
559 ctx->viewport.scale[2] = 0.5f;
560 ctx->viewport.scale[3] = 1.0f;
561 ctx->viewport.translate[0] = 0.5f * dst_surface->width;
562 ctx->viewport.translate[1] = 0.5f * dst_surface->height;
563 ctx->viewport.translate[2] = 0.5f;
564 ctx->viewport.translate[3] = 0.0f;
565 cso_set_viewport(ctx->cso, &ctx->viewport);
566
567 /* texture */
568 cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view);
569
570 /* shaders */
571 if (dst_is_depth) {
572 set_depth_fragment_shader(ctx);
573 } else {
574 set_fragment_shader(ctx, writemask);
575 }
576 set_vertex_shader(ctx);
577
578 /* drawing dest */
579 memset(&fb, 0, sizeof(fb));
580 fb.width = dst_surface->width;
581 fb.height = dst_surface->height;
582 if (dst_is_depth) {
583 fb.zsbuf = dst_surface;
584 } else {
585 fb.nr_cbufs = 1;
586 fb.cbufs[0] = dst_surface;
587 }
588 cso_set_framebuffer(ctx->cso, &fb);
589
590 /* draw quad */
591 offset = setup_vertex_data_tex(ctx,
592 (float) dstX0 / dst_surface->width * 2.0f - 1.0f,
593 (float) dstY0 / dst_surface->height * 2.0f - 1.0f,
594 (float) dstX1 / dst_surface->width * 2.0f - 1.0f,
595 (float) dstY1 / dst_surface->height * 2.0f - 1.0f,
596 s0, t0,
597 s1, t1,
598 z);
599
600 util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, offset,
601 PIPE_PRIM_TRIANGLE_FAN,
602 4, /* verts */
603 2); /* attribs/vert */
604
605 /* restore state we changed */
606 cso_restore_blend(ctx->cso);
607 cso_restore_depth_stencil_alpha(ctx->cso);
608 cso_restore_rasterizer(ctx->cso);
609 cso_restore_samplers(ctx->cso);
610 cso_restore_fragment_sampler_views(ctx->cso);
611 cso_restore_viewport(ctx->cso);
612 cso_restore_framebuffer(ctx->cso);
613 cso_restore_fragment_shader(ctx->cso);
614 cso_restore_vertex_shader(ctx->cso);
615 cso_restore_clip(ctx->cso);
616 cso_restore_vertex_elements(ctx->cso);
617 cso_restore_vertex_buffers(ctx->cso);
618
619 pipe_sampler_view_reference(&sampler_view, NULL);
620 if (dst_surface != dst)
621 pipe_surface_reference(&dst_surface, NULL);
622 }
623
624
625 void
626 util_blit_pixels(struct blit_state *ctx,
627 struct pipe_resource *src_tex,
628 unsigned src_level,
629 int srcX0, int srcY0,
630 int srcX1, int srcY1,
631 int srcZ,
632 struct pipe_surface *dst,
633 int dstX0, int dstY0,
634 int dstX1, int dstY1,
635 float z, uint filter )
636 {
637 util_blit_pixels_writemask( ctx, src_tex,
638 src_level,
639 srcX0, srcY0,
640 srcX1, srcY1,
641 srcZ,
642 dst,
643 dstX0, dstY0,
644 dstX1, dstY1,
645 z, filter,
646 TGSI_WRITEMASK_XYZW );
647 }
648
649
650 /* Release vertex buffer at end of frame to avoid synchronous
651 * rendering.
652 */
653 void util_blit_flush( struct blit_state *ctx )
654 {
655 pipe_resource_reference(&ctx->vbuf, NULL);
656 ctx->vbuf_slot = 0;
657 }
658
659
660
661 /**
662 * Copy pixel block from src texture to dst surface.
663 *
664 * XXX Should support selection of level.
665 * XXX need some control over blitting Z and/or stencil.
666 */
667 void
668 util_blit_pixels_tex(struct blit_state *ctx,
669 struct pipe_sampler_view *src_sampler_view,
670 int srcX0, int srcY0,
671 int srcX1, int srcY1,
672 struct pipe_surface *dst,
673 int dstX0, int dstY0,
674 int dstX1, int dstY1,
675 float z, uint filter)
676 {
677 boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
678 struct pipe_framebuffer_state fb;
679 float s0, t0, s1, t1;
680 unsigned offset;
681 struct pipe_resource *tex = src_sampler_view->texture;
682
683 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
684 filter == PIPE_TEX_MIPFILTER_LINEAR);
685
686 assert(tex);
687 assert(tex->width0 != 0);
688 assert(tex->height0 != 0);
689
690 s0 = srcX0;
691 s1 = srcX1;
692 t0 = srcY0;
693 t1 = srcY1;
694
695 if(normalized)
696 {
697 s0 /= (float)tex->width0;
698 s1 /= (float)tex->width0;
699 t0 /= (float)tex->height0;
700 t1 /= (float)tex->height0;
701 }
702
703 assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
704 PIPE_TEXTURE_2D,
705 dst->texture->nr_samples,
706 PIPE_BIND_RENDER_TARGET));
707
708 /* save state (restored below) */
709 cso_save_blend(ctx->cso);
710 cso_save_depth_stencil_alpha(ctx->cso);
711 cso_save_rasterizer(ctx->cso);
712 cso_save_samplers(ctx->cso);
713 cso_save_fragment_sampler_views(ctx->cso);
714 cso_save_viewport(ctx->cso);
715 cso_save_framebuffer(ctx->cso);
716 cso_save_fragment_shader(ctx->cso);
717 cso_save_vertex_shader(ctx->cso);
718 cso_save_clip(ctx->cso);
719 cso_save_vertex_elements(ctx->cso);
720 cso_save_vertex_buffers(ctx->cso);
721
722 /* set misc state we care about */
723 cso_set_blend(ctx->cso, &ctx->blend);
724 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil_keep);
725 cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
726 cso_set_clip(ctx->cso, &ctx->clip);
727 cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
728
729 /* sampler */
730 ctx->sampler.normalized_coords = normalized;
731 ctx->sampler.min_img_filter = filter;
732 ctx->sampler.mag_img_filter = filter;
733 cso_single_sampler(ctx->cso, 0, &ctx->sampler);
734 cso_single_sampler_done(ctx->cso);
735
736 /* viewport */
737 ctx->viewport.scale[0] = 0.5f * dst->width;
738 ctx->viewport.scale[1] = 0.5f * dst->height;
739 ctx->viewport.scale[2] = 0.5f;
740 ctx->viewport.scale[3] = 1.0f;
741 ctx->viewport.translate[0] = 0.5f * dst->width;
742 ctx->viewport.translate[1] = 0.5f * dst->height;
743 ctx->viewport.translate[2] = 0.5f;
744 ctx->viewport.translate[3] = 0.0f;
745 cso_set_viewport(ctx->cso, &ctx->viewport);
746
747 /* texture */
748 cso_set_fragment_sampler_views(ctx->cso, 1, &src_sampler_view);
749
750 /* shaders */
751 set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW);
752 set_vertex_shader(ctx);
753
754 /* drawing dest */
755 memset(&fb, 0, sizeof(fb));
756 fb.width = dst->width;
757 fb.height = dst->height;
758 fb.nr_cbufs = 1;
759 fb.cbufs[0] = dst;
760 cso_set_framebuffer(ctx->cso, &fb);
761
762 /* draw quad */
763 offset = setup_vertex_data_tex(ctx,
764 (float) dstX0 / dst->width * 2.0f - 1.0f,
765 (float) dstY0 / dst->height * 2.0f - 1.0f,
766 (float) dstX1 / dst->width * 2.0f - 1.0f,
767 (float) dstY1 / dst->height * 2.0f - 1.0f,
768 s0, t0, s1, t1,
769 z);
770
771 util_draw_vertex_buffer(ctx->pipe, ctx->cso,
772 ctx->vbuf, offset,
773 PIPE_PRIM_TRIANGLE_FAN,
774 4, /* verts */
775 2); /* attribs/vert */
776
777 /* restore state we changed */
778 cso_restore_blend(ctx->cso);
779 cso_restore_depth_stencil_alpha(ctx->cso);
780 cso_restore_rasterizer(ctx->cso);
781 cso_restore_samplers(ctx->cso);
782 cso_restore_fragment_sampler_views(ctx->cso);
783 cso_restore_viewport(ctx->cso);
784 cso_restore_framebuffer(ctx->cso);
785 cso_restore_fragment_shader(ctx->cso);
786 cso_restore_vertex_shader(ctx->cso);
787 cso_restore_clip(ctx->cso);
788 cso_restore_vertex_elements(ctx->cso);
789 cso_restore_vertex_buffers(ctx->cso);
790 }