u_blit.c revision 6b3f1ae12b7d53bf88cdcf0e78803e929cdf5bbd
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
54struct 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 */
89struct blit_state *
90util_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.gl_rasterization_rules = 1;
122   ctx->rasterizer.depth_clip = 1;
123
124   /* samplers */
125   ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
126   ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
127   ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
128   ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
129   ctx->sampler.min_img_filter = 0; /* set later */
130   ctx->sampler.mag_img_filter = 0; /* set later */
131
132   /* vertex elements state */
133   for (i = 0; i < 2; i++) {
134      ctx->velem[i].src_offset = i * 4 * sizeof(float);
135      ctx->velem[i].instance_divisor = 0;
136      ctx->velem[i].vertex_buffer_index = 0;
137      ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
138   }
139
140   ctx->vbuf = NULL;
141
142   /* init vertex data that doesn't change */
143   for (i = 0; i < 4; i++) {
144      ctx->vertices[i][0][3] = 1.0f; /* w */
145      ctx->vertices[i][1][2] = 0.0f; /* r */
146      ctx->vertices[i][1][3] = 1.0f; /* q */
147   }
148
149   if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
150      ctx->internal_target = PIPE_TEXTURE_2D;
151   else
152      ctx->internal_target = PIPE_TEXTURE_RECT;
153
154   ctx->has_stencil_export =
155      pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT);
156
157   return ctx;
158}
159
160
161/**
162 * Destroy a blit context
163 */
164void
165util_destroy_blit(struct blit_state *ctx)
166{
167   struct pipe_context *pipe = ctx->pipe;
168   unsigned i, j;
169
170   if (ctx->vs)
171      pipe->delete_vs_state(pipe, ctx->vs);
172
173   for (i = 0; i < Elements(ctx->fs); i++) {
174      for (j = 0; j < Elements(ctx->fs[i]); j++) {
175         if (ctx->fs[i][j])
176            pipe->delete_fs_state(pipe, ctx->fs[i][j]);
177      }
178   }
179
180   for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) {
181      if (ctx->fs_depthstencil[i]) {
182         pipe->delete_fs_state(pipe, ctx->fs_depthstencil[i]);
183      }
184      if (ctx->fs_depth[i]) {
185         pipe->delete_fs_state(pipe, ctx->fs_depth[i]);
186      }
187      if (ctx->fs_stencil[i]) {
188         pipe->delete_fs_state(pipe, ctx->fs_stencil[i]);
189      }
190   }
191
192   pipe_resource_reference(&ctx->vbuf, NULL);
193
194   FREE(ctx);
195}
196
197
198/**
199 * Helper function to set the fragment shaders.
200 */
201static INLINE void
202set_fragment_shader(struct blit_state *ctx, uint writemask,
203                    enum pipe_texture_target pipe_tex)
204{
205   if (!ctx->fs[pipe_tex][writemask]) {
206      unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex);
207
208      ctx->fs[pipe_tex][writemask] =
209         util_make_fragment_tex_shader_writemask(ctx->pipe, tgsi_tex,
210                                                 TGSI_INTERPOLATE_LINEAR,
211                                                 writemask);
212   }
213
214   cso_set_fragment_shader_handle(ctx->cso, ctx->fs[pipe_tex][writemask]);
215}
216
217
218/**
219 * Helper function to set the shader which writes depth and stencil.
220 */
221static INLINE void
222set_depthstencil_fragment_shader(struct blit_state *ctx,
223                                 enum pipe_texture_target pipe_tex)
224{
225   if (!ctx->fs_depthstencil[pipe_tex]) {
226      unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex);
227
228      ctx->fs_depthstencil[pipe_tex] =
229         util_make_fragment_tex_shader_writedepthstencil(ctx->pipe, tgsi_tex,
230                                                  TGSI_INTERPOLATE_LINEAR);
231   }
232
233   cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depthstencil[pipe_tex]);
234}
235
236
237/**
238 * Helper function to set the shader which writes depth.
239 */
240static INLINE void
241set_depth_fragment_shader(struct blit_state *ctx,
242                          enum pipe_texture_target pipe_tex)
243{
244   if (!ctx->fs_depth[pipe_tex]) {
245      unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex);
246
247      ctx->fs_depth[pipe_tex] =
248         util_make_fragment_tex_shader_writedepth(ctx->pipe, tgsi_tex,
249                                                  TGSI_INTERPOLATE_LINEAR);
250   }
251
252   cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth[pipe_tex]);
253}
254
255
256/**
257 * Helper function to set the shader which writes stencil.
258 */
259static INLINE void
260set_stencil_fragment_shader(struct blit_state *ctx,
261                            enum pipe_texture_target pipe_tex)
262{
263   if (!ctx->fs_stencil[pipe_tex]) {
264      unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex);
265
266      ctx->fs_stencil[pipe_tex] =
267         util_make_fragment_tex_shader_writestencil(ctx->pipe, tgsi_tex,
268                                                    TGSI_INTERPOLATE_LINEAR);
269   }
270
271   cso_set_fragment_shader_handle(ctx->cso, ctx->fs_stencil[pipe_tex]);
272}
273
274
275/**
276 * Helper function to set the vertex shader.
277 */
278static INLINE void
279set_vertex_shader(struct blit_state *ctx)
280{
281   /* vertex shader - still required to provide the linkage between
282    * fragment shader input semantics and vertex_element/buffers.
283    */
284   if (!ctx->vs) {
285      const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
286                                      TGSI_SEMANTIC_GENERIC };
287      const uint semantic_indexes[] = { 0, 0 };
288      ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2,
289                                                    semantic_names,
290                                                    semantic_indexes);
291   }
292
293   cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
294}
295
296
297/**
298 * Get offset of next free slot in vertex buffer for quad vertices.
299 */
300static unsigned
301get_next_slot( struct blit_state *ctx )
302{
303   const unsigned max_slots = 4096 / sizeof ctx->vertices;
304
305   if (ctx->vbuf_slot >= max_slots) {
306      pipe_resource_reference(&ctx->vbuf, NULL);
307      ctx->vbuf_slot = 0;
308   }
309
310   if (!ctx->vbuf) {
311      ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
312                                     PIPE_BIND_VERTEX_BUFFER,
313                                     PIPE_USAGE_STREAM,
314                                     max_slots * sizeof ctx->vertices);
315   }
316
317   return ctx->vbuf_slot++ * sizeof ctx->vertices;
318}
319
320
321
322
323/**
324 * Setup vertex data for the textured quad we'll draw.
325 * Note: y=0=top
326 */
327static unsigned
328setup_vertex_data_tex(struct blit_state *ctx,
329                      float x0, float y0, float x1, float y1,
330                      float s0, float t0, float s1, float t1,
331                      float z)
332{
333   unsigned offset;
334
335   ctx->vertices[0][0][0] = x0;
336   ctx->vertices[0][0][1] = y0;
337   ctx->vertices[0][0][2] = z;
338   ctx->vertices[0][1][0] = s0; /*s*/
339   ctx->vertices[0][1][1] = t0; /*t*/
340
341   ctx->vertices[1][0][0] = x1;
342   ctx->vertices[1][0][1] = y0;
343   ctx->vertices[1][0][2] = z;
344   ctx->vertices[1][1][0] = s1; /*s*/
345   ctx->vertices[1][1][1] = t0; /*t*/
346
347   ctx->vertices[2][0][0] = x1;
348   ctx->vertices[2][0][1] = y1;
349   ctx->vertices[2][0][2] = z;
350   ctx->vertices[2][1][0] = s1;
351   ctx->vertices[2][1][1] = t1;
352
353   ctx->vertices[3][0][0] = x0;
354   ctx->vertices[3][0][1] = y1;
355   ctx->vertices[3][0][2] = z;
356   ctx->vertices[3][1][0] = s0;
357   ctx->vertices[3][1][1] = t1;
358
359   offset = get_next_slot( ctx );
360
361   if (ctx->vbuf) {
362      pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf,
363                                  offset, sizeof(ctx->vertices), ctx->vertices);
364   }
365
366   return offset;
367}
368
369
370/**
371 * \return TRUE if two regions overlap, FALSE otherwise
372 */
373static boolean
374regions_overlap(int srcX0, int srcY0,
375                int srcX1, int srcY1,
376                int dstX0, int dstY0,
377                int dstX1, int dstY1)
378{
379   if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1))
380      return FALSE; /* src completely left of dst */
381
382   if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1))
383      return FALSE; /* dst completely left of src */
384
385   if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1))
386      return FALSE; /* src completely above dst */
387
388   if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1))
389      return FALSE; /* dst completely above src */
390
391   return TRUE; /* some overlap */
392}
393
394
395/**
396 * Can we blit from src format to dest format with a simple copy?
397 */
398static boolean
399formats_compatible(enum pipe_format src_format,
400                   enum pipe_format dst_format)
401{
402   if (src_format == dst_format) {
403      return TRUE;
404   }
405   else {
406      const struct util_format_description *src_desc =
407         util_format_description(src_format);
408      const struct util_format_description *dst_desc =
409         util_format_description(dst_format);
410      return util_is_format_compatible(src_desc, dst_desc);
411   }
412}
413
414
415/**
416 * Copy pixel block from src surface to dst surface.
417 * Overlapping regions are acceptable.
418 * Flipping and stretching are supported.
419 * \param filter  one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR
420 * \param writemask  controls which channels in the dest surface are sourced
421 *                   from the src surface.  Disabled channels are sourced
422 *                   from (0,0,0,1).
423 */
424void
425util_blit_pixels(struct blit_state *ctx,
426                 struct pipe_resource *src_tex,
427                 unsigned src_level,
428                 int srcX0, int srcY0,
429                 int srcX1, int srcY1,
430                 int srcZ0,
431                 struct pipe_surface *dst,
432                 int dstX0, int dstY0,
433                 int dstX1, int dstY1,
434                 float z, uint filter,
435                 uint writemask, uint zs_writemask)
436{
437   struct pipe_context *pipe = ctx->pipe;
438   struct pipe_screen *screen = pipe->screen;
439   enum pipe_format src_format, dst_format;
440   struct pipe_sampler_view *sampler_view = NULL;
441   struct pipe_sampler_view sv_templ;
442   struct pipe_surface *dst_surface;
443   struct pipe_framebuffer_state fb;
444   const int srcW = abs(srcX1 - srcX0);
445   const int srcH = abs(srcY1 - srcY0);
446   unsigned offset;
447   boolean overlap;
448   float s0, t0, s1, t1;
449   boolean normalized;
450   boolean is_stencil, is_depth, blit_depth, blit_stencil;
451   const struct util_format_description *src_desc =
452         util_format_description(src_tex->format);
453
454   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
455          filter == PIPE_TEX_MIPFILTER_LINEAR);
456
457   assert(src_level <= src_tex->last_level);
458
459   /* do the regions overlap? */
460   overlap = src_tex == dst->texture &&
461             dst->u.tex.level == src_level &&
462             dst->u.tex.first_layer == srcZ0 &&
463      regions_overlap(srcX0, srcY0, srcX1, srcY1,
464                      dstX0, dstY0, dstX1, dstY1);
465
466   src_format = util_format_linear(src_tex->format);
467   dst_format = util_format_linear(dst->format);
468
469   /* See whether we will blit depth or stencil. */
470   is_depth = util_format_has_depth(src_desc);
471   is_stencil = util_format_has_stencil(src_desc);
472
473   blit_depth = is_depth && (zs_writemask & BLIT_WRITEMASK_Z);
474   blit_stencil = is_stencil && (zs_writemask & BLIT_WRITEMASK_STENCIL);
475
476   assert((writemask && !zs_writemask && !is_depth && !is_stencil) ||
477          (!writemask && (blit_depth || blit_stencil)));
478
479   /*
480    * Check for simple case:  no format conversion, no flipping, no stretching,
481    * no overlapping, same number of samples.
482    * Filter mode should not matter since there's no stretching.
483    */
484   if (formats_compatible(src_format, dst_format) &&
485       src_tex->nr_samples == dst->texture->nr_samples &&
486       is_stencil == blit_stencil &&
487       is_depth == blit_depth &&
488       srcX0 < srcX1 &&
489       dstX0 < dstX1 &&
490       srcY0 < srcY1 &&
491       dstY0 < dstY1 &&
492       (dstX1 - dstX0) == (srcX1 - srcX0) &&
493       (dstY1 - dstY0) == (srcY1 - srcY0) &&
494       !overlap) {
495      struct pipe_box src_box;
496      src_box.x = srcX0;
497      src_box.y = srcY0;
498      src_box.z = srcZ0;
499      src_box.width = srcW;
500      src_box.height = srcH;
501      src_box.depth = 1;
502      pipe->resource_copy_region(pipe,
503                                 dst->texture, dst->u.tex.level,
504                                 dstX0, dstY0, dst->u.tex.first_layer,/* dest */
505                                 src_tex, src_level,
506                                 &src_box);
507      return;
508   }
509
510   /* It's a mistake to call this function with a stencil format and
511    * without shader stencil export. We don't do software fallbacks here.
512    * Ignore stencil and only copy depth.
513    */
514   if (blit_stencil && !ctx->has_stencil_export) {
515      blit_stencil = FALSE;
516
517      if (!blit_depth)
518         return;
519   }
520
521   if (dst_format == dst->format) {
522      dst_surface = dst;
523   } else {
524      struct pipe_surface templ = *dst;
525      templ.format = dst_format;
526      dst_surface = pipe->create_surface(pipe, dst->texture, &templ);
527   }
528
529   /* Create a temporary texture when src and dest alias.
530    */
531   if (src_tex == dst_surface->texture &&
532       dst_surface->u.tex.level == src_level &&
533       dst_surface->u.tex.first_layer == srcZ0) {
534      /* Make a temporary texture which contains a copy of the source pixels.
535       * Then we'll sample from the temporary texture.
536       */
537      struct pipe_resource texTemp;
538      struct pipe_resource *tex;
539      struct pipe_sampler_view sv_templ;
540      struct pipe_box src_box;
541      const int srcLeft = MIN2(srcX0, srcX1);
542      const int srcTop = MIN2(srcY0, srcY1);
543
544      if (srcLeft != srcX0) {
545         /* left-right flip */
546         int tmp = dstX0;
547         dstX0 = dstX1;
548         dstX1 = tmp;
549      }
550
551      if (srcTop != srcY0) {
552         /* up-down flip */
553         int tmp = dstY0;
554         dstY0 = dstY1;
555         dstY1 = tmp;
556      }
557
558      /* create temp texture */
559      memset(&texTemp, 0, sizeof(texTemp));
560      texTemp.target = ctx->internal_target;
561      texTemp.format = src_format;
562      texTemp.last_level = 0;
563      texTemp.width0 = srcW;
564      texTemp.height0 = srcH;
565      texTemp.depth0 = 1;
566      texTemp.array_size = 1;
567      texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
568
569      tex = screen->resource_create(screen, &texTemp);
570      if (!tex)
571         return;
572
573      src_box.x = srcLeft;
574      src_box.y = srcTop;
575      src_box.z = srcZ0;
576      src_box.width = srcW;
577      src_box.height = srcH;
578      src_box.depth = 1;
579      /* load temp texture */
580      pipe->resource_copy_region(pipe,
581                                 tex, 0, 0, 0, 0,  /* dest */
582                                 src_tex, src_level, &src_box);
583
584      normalized = tex->target != PIPE_TEXTURE_RECT;
585      if(normalized) {
586         s0 = 0.0f;
587         s1 = 1.0f;
588         t0 = 0.0f;
589         t1 = 1.0f;
590      }
591      else {
592         s0 = 0;
593         s1 = srcW;
594         t0 = 0;
595         t1 = srcH;
596      }
597
598      u_sampler_view_default_template(&sv_templ, tex, tex->format);
599      if (!blit_depth && blit_stencil) {
600         /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
601         sv_templ.format = util_format_stencil_only(tex->format);
602         assert(sv_templ.format != PIPE_FORMAT_NONE);
603      }
604      sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ);
605
606      if (!sampler_view) {
607         pipe_resource_reference(&tex, NULL);
608         return;
609      }
610      pipe_resource_reference(&tex, NULL);
611   }
612   else {
613      /* Directly sample from the source resource/texture */
614      u_sampler_view_default_template(&sv_templ, src_tex, src_format);
615      if (!blit_depth && blit_stencil) {
616         /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
617         sv_templ.format = util_format_stencil_only(src_format);
618         assert(sv_templ.format != PIPE_FORMAT_NONE);
619      }
620      sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);
621
622      if (!sampler_view) {
623         return;
624      }
625
626      s0 = srcX0;
627      s1 = srcX1;
628      t0 = srcY0;
629      t1 = srcY1;
630      normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT;
631      if(normalized)
632      {
633         s0 /= (float)(u_minify(sampler_view->texture->width0, src_level));
634         s1 /= (float)(u_minify(sampler_view->texture->width0, src_level));
635         t0 /= (float)(u_minify(sampler_view->texture->height0, src_level));
636         t1 /= (float)(u_minify(sampler_view->texture->height0, src_level));
637      }
638   }
639
640   assert(screen->is_format_supported(screen, sampler_view->format,
641                     ctx->internal_target, sampler_view->texture->nr_samples,
642                     PIPE_BIND_SAMPLER_VIEW));
643   assert(screen->is_format_supported(screen, dst_format, ctx->internal_target,
644                     dst_surface->texture->nr_samples,
645                     is_depth || is_stencil ? PIPE_BIND_DEPTH_STENCIL :
646                                              PIPE_BIND_RENDER_TARGET));
647
648   /* save state (restored below) */
649   cso_save_blend(ctx->cso);
650   cso_save_depth_stencil_alpha(ctx->cso);
651   cso_save_rasterizer(ctx->cso);
652   cso_save_sample_mask(ctx->cso);
653   cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
654   cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
655   cso_save_stream_outputs(ctx->cso);
656   cso_save_viewport(ctx->cso);
657   cso_save_framebuffer(ctx->cso);
658   cso_save_fragment_shader(ctx->cso);
659   cso_save_vertex_shader(ctx->cso);
660   cso_save_geometry_shader(ctx->cso);
661   cso_save_vertex_elements(ctx->cso);
662   cso_save_vertex_buffers(ctx->cso);
663
664   /* set misc state we care about */
665   if (writemask)
666      cso_set_blend(ctx->cso, &ctx->blend_write_color);
667   else
668      cso_set_blend(ctx->cso, &ctx->blend_keep_color);
669
670   cso_set_sample_mask(ctx->cso, ~0);
671   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
672   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
673   cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
674
675   /* default sampler state */
676   ctx->sampler.normalized_coords = normalized;
677   ctx->sampler.min_img_filter = filter;
678   ctx->sampler.mag_img_filter = filter;
679   ctx->sampler.min_lod = src_level;
680   ctx->sampler.max_lod = src_level;
681
682   /* Depth stencil state, fragment shader and sampler setup depending on what
683    * we blit.
684    */
685   if (blit_depth && blit_stencil) {
686      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
687      /* don't filter stencil */
688      ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
689      ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
690      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &ctx->sampler);
691
692      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depthstencil);
693      set_depthstencil_fragment_shader(ctx, sampler_view->texture->target);
694   }
695   else if (blit_depth) {
696      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
697      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depth);
698      set_depth_fragment_shader(ctx, sampler_view->texture->target);
699   }
700   else if (blit_stencil) {
701      /* don't filter stencil */
702      ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
703      ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
704      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
705
706      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_stencil);
707      set_stencil_fragment_shader(ctx, sampler_view->texture->target);
708   }
709   else { /* color */
710      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
711      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
712      set_fragment_shader(ctx, writemask, sampler_view->texture->target);
713   }
714   cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);
715
716   /* textures */
717   if (blit_depth && blit_stencil) {
718      /* Setup two samplers, one for depth and the other one for stencil. */
719      struct pipe_sampler_view templ;
720      struct pipe_sampler_view *views[2];
721
722      templ = *sampler_view;
723      templ.format = util_format_stencil_only(templ.format);
724      assert(templ.format != PIPE_FORMAT_NONE);
725
726      views[0] = sampler_view;
727      views[1] = pipe->create_sampler_view(pipe, views[0]->texture, &templ);
728      cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 2, views);
729
730      pipe_sampler_view_reference(&views[1], NULL);
731   }
732   else {
733      cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &sampler_view);
734   }
735
736   /* viewport */
737   ctx->viewport.scale[0] = 0.5f * dst_surface->width;
738   ctx->viewport.scale[1] = 0.5f * dst_surface->height;
739   ctx->viewport.scale[2] = 0.5f;
740   ctx->viewport.scale[3] = 1.0f;
741   ctx->viewport.translate[0] = 0.5f * dst_surface->width;
742   ctx->viewport.translate[1] = 0.5f * dst_surface->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   set_vertex_shader(ctx);
748   cso_set_geometry_shader_handle(ctx->cso, NULL);
749
750   /* drawing dest */
751   memset(&fb, 0, sizeof(fb));
752   fb.width = dst_surface->width;
753   fb.height = dst_surface->height;
754   if (blit_depth || blit_stencil) {
755      fb.zsbuf = dst_surface;
756   } else {
757      fb.nr_cbufs = 1;
758      fb.cbufs[0] = dst_surface;
759   }
760   cso_set_framebuffer(ctx->cso, &fb);
761
762   /* draw quad */
763   offset = setup_vertex_data_tex(ctx,
764                                  (float) dstX0 / dst_surface->width * 2.0f - 1.0f,
765                                  (float) dstY0 / dst_surface->height * 2.0f - 1.0f,
766                                  (float) dstX1 / dst_surface->width * 2.0f - 1.0f,
767                                  (float) dstY1 / dst_surface->height * 2.0f - 1.0f,
768                                  s0, t0,
769                                  s1, t1,
770                                  z);
771
772   if (ctx->vbuf) {
773      util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, offset,
774                              PIPE_PRIM_TRIANGLE_FAN,
775                              4,  /* verts */
776                              2); /* attribs/vert */
777   }
778
779   /* restore state we changed */
780   cso_restore_blend(ctx->cso);
781   cso_restore_depth_stencil_alpha(ctx->cso);
782   cso_restore_rasterizer(ctx->cso);
783   cso_restore_sample_mask(ctx->cso);
784   cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
785   cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
786   cso_restore_viewport(ctx->cso);
787   cso_restore_framebuffer(ctx->cso);
788   cso_restore_fragment_shader(ctx->cso);
789   cso_restore_vertex_shader(ctx->cso);
790   cso_restore_geometry_shader(ctx->cso);
791   cso_restore_vertex_elements(ctx->cso);
792   cso_restore_vertex_buffers(ctx->cso);
793   cso_restore_stream_outputs(ctx->cso);
794
795   pipe_sampler_view_reference(&sampler_view, NULL);
796   if (dst_surface != dst)
797      pipe_surface_reference(&dst_surface, NULL);
798}
799
800
801/**
802 * Copy pixel block from src texture to dst surface.
803 * The sampler view's first_level field indicates the source
804 * mipmap level to use.
805 * XXX need some control over blitting Z and/or stencil.
806 */
807void
808util_blit_pixels_tex(struct blit_state *ctx,
809                     struct pipe_sampler_view *src_sampler_view,
810                     int srcX0, int srcY0,
811                     int srcX1, int srcY1,
812                     struct pipe_surface *dst,
813                     int dstX0, int dstY0,
814                     int dstX1, int dstY1,
815                     float z, uint filter)
816{
817   boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
818   struct pipe_framebuffer_state fb;
819   float s0, t0, s1, t1;
820   unsigned offset;
821   struct pipe_resource *tex = src_sampler_view->texture;
822
823   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
824          filter == PIPE_TEX_MIPFILTER_LINEAR);
825
826   assert(tex);
827   assert(tex->width0 != 0);
828   assert(tex->height0 != 0);
829
830   s0 = srcX0;
831   s1 = srcX1;
832   t0 = srcY0;
833   t1 = srcY1;
834
835   if(normalized)
836   {
837      /* normalize according to the mipmap level's size */
838      int level = src_sampler_view->u.tex.first_level;
839      float w = (float) u_minify(tex->width0, level);
840      float h = (float) u_minify(tex->height0, level);
841      s0 /= w;
842      s1 /= w;
843      t0 /= h;
844      t1 /= h;
845   }
846
847   assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
848                                                 PIPE_TEXTURE_2D,
849                                                 dst->texture->nr_samples,
850                                                 PIPE_BIND_RENDER_TARGET));
851
852   /* save state (restored below) */
853   cso_save_blend(ctx->cso);
854   cso_save_depth_stencil_alpha(ctx->cso);
855   cso_save_rasterizer(ctx->cso);
856   cso_save_sample_mask(ctx->cso);
857   cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
858   cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
859   cso_save_stream_outputs(ctx->cso);
860   cso_save_viewport(ctx->cso);
861   cso_save_framebuffer(ctx->cso);
862   cso_save_fragment_shader(ctx->cso);
863   cso_save_vertex_shader(ctx->cso);
864   cso_save_geometry_shader(ctx->cso);
865   cso_save_vertex_elements(ctx->cso);
866   cso_save_vertex_buffers(ctx->cso);
867
868   /* set misc state we care about */
869   cso_set_blend(ctx->cso, &ctx->blend_write_color);
870   cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
871   cso_set_sample_mask(ctx->cso, ~0);
872   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
873   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
874   cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
875
876   /* sampler */
877   ctx->sampler.normalized_coords = normalized;
878   ctx->sampler.min_img_filter = filter;
879   ctx->sampler.mag_img_filter = filter;
880   cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
881   cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);
882
883   /* viewport */
884   ctx->viewport.scale[0] = 0.5f * dst->width;
885   ctx->viewport.scale[1] = 0.5f * dst->height;
886   ctx->viewport.scale[2] = 0.5f;
887   ctx->viewport.scale[3] = 1.0f;
888   ctx->viewport.translate[0] = 0.5f * dst->width;
889   ctx->viewport.translate[1] = 0.5f * dst->height;
890   ctx->viewport.translate[2] = 0.5f;
891   ctx->viewport.translate[3] = 0.0f;
892   cso_set_viewport(ctx->cso, &ctx->viewport);
893
894   /* texture */
895   cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &src_sampler_view);
896
897   /* shaders */
898   set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW,
899                       src_sampler_view->texture->target);
900   set_vertex_shader(ctx);
901   cso_set_geometry_shader_handle(ctx->cso, NULL);
902
903   /* drawing dest */
904   memset(&fb, 0, sizeof(fb));
905   fb.width = dst->width;
906   fb.height = dst->height;
907   fb.nr_cbufs = 1;
908   fb.cbufs[0] = dst;
909   cso_set_framebuffer(ctx->cso, &fb);
910
911   /* draw quad */
912   offset = setup_vertex_data_tex(ctx,
913                                  (float) dstX0 / dst->width * 2.0f - 1.0f,
914                                  (float) dstY0 / dst->height * 2.0f - 1.0f,
915                                  (float) dstX1 / dst->width * 2.0f - 1.0f,
916                                  (float) dstY1 / dst->height * 2.0f - 1.0f,
917                                  s0, t0, s1, t1,
918                                  z);
919
920   util_draw_vertex_buffer(ctx->pipe, ctx->cso,
921                           ctx->vbuf, offset,
922                           PIPE_PRIM_TRIANGLE_FAN,
923                           4,  /* verts */
924                           2); /* attribs/vert */
925
926   /* restore state we changed */
927   cso_restore_blend(ctx->cso);
928   cso_restore_depth_stencil_alpha(ctx->cso);
929   cso_restore_rasterizer(ctx->cso);
930   cso_restore_sample_mask(ctx->cso);
931   cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
932   cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
933   cso_restore_viewport(ctx->cso);
934   cso_restore_framebuffer(ctx->cso);
935   cso_restore_fragment_shader(ctx->cso);
936   cso_restore_vertex_shader(ctx->cso);
937   cso_restore_geometry_shader(ctx->cso);
938   cso_restore_vertex_elements(ctx->cso);
939   cso_restore_vertex_buffers(ctx->cso);
940   cso_restore_stream_outputs(ctx->cso);
941}
942