u_blit.c revision b7c4ee21c53a73d84e352d6f3db2547f6434d14e
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->texture->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   /* XXX Reading multisample textures is unimplemented. */
511   assert(src_tex->nr_samples <= 1);
512   if (src_tex->nr_samples > 1) {
513      return;
514   }
515
516   /* It's a mistake to call this function with a stencil format and
517    * without shader stencil export. We don't do software fallbacks here.
518    * Ignore stencil and only copy depth.
519    */
520   if (blit_stencil && !ctx->has_stencil_export) {
521      blit_stencil = FALSE;
522
523      if (!blit_depth)
524         return;
525   }
526
527   if (dst_format == dst->format) {
528      dst_surface = dst;
529   } else {
530      struct pipe_surface templ = *dst;
531      templ.format = dst_format;
532      dst_surface = pipe->create_surface(pipe, dst->texture, &templ);
533   }
534
535   /* Create a temporary texture when src and dest alias.
536    */
537   if (src_tex == dst_surface->texture &&
538       dst_surface->u.tex.level == src_level &&
539       dst_surface->u.tex.first_layer == srcZ0) {
540      /* Make a temporary texture which contains a copy of the source pixels.
541       * Then we'll sample from the temporary texture.
542       */
543      struct pipe_resource texTemp;
544      struct pipe_resource *tex;
545      struct pipe_sampler_view sv_templ;
546      struct pipe_box src_box;
547      const int srcLeft = MIN2(srcX0, srcX1);
548      const int srcTop = MIN2(srcY0, srcY1);
549
550      if (srcLeft != srcX0) {
551         /* left-right flip */
552         int tmp = dstX0;
553         dstX0 = dstX1;
554         dstX1 = tmp;
555      }
556
557      if (srcTop != srcY0) {
558         /* up-down flip */
559         int tmp = dstY0;
560         dstY0 = dstY1;
561         dstY1 = tmp;
562      }
563
564      /* create temp texture */
565      memset(&texTemp, 0, sizeof(texTemp));
566      texTemp.target = ctx->internal_target;
567      texTemp.format = src_format;
568      texTemp.last_level = 0;
569      texTemp.width0 = srcW;
570      texTemp.height0 = srcH;
571      texTemp.depth0 = 1;
572      texTemp.array_size = 1;
573      texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
574
575      tex = screen->resource_create(screen, &texTemp);
576      if (!tex)
577         return;
578
579      src_box.x = srcLeft;
580      src_box.y = srcTop;
581      src_box.z = srcZ0;
582      src_box.width = srcW;
583      src_box.height = srcH;
584      src_box.depth = 1;
585      /* load temp texture */
586      pipe->resource_copy_region(pipe,
587                                 tex, 0, 0, 0, 0,  /* dest */
588                                 src_tex, src_level, &src_box);
589
590      normalized = tex->target != PIPE_TEXTURE_RECT;
591      if(normalized) {
592         s0 = 0.0f;
593         s1 = 1.0f;
594         t0 = 0.0f;
595         t1 = 1.0f;
596      }
597      else {
598         s0 = 0;
599         s1 = srcW;
600         t0 = 0;
601         t1 = srcH;
602      }
603
604      u_sampler_view_default_template(&sv_templ, tex, tex->format);
605      if (!blit_depth && blit_stencil) {
606         /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
607         sv_templ.format = util_format_stencil_only(tex->format);
608         assert(sv_templ.format != PIPE_FORMAT_NONE);
609      }
610      sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ);
611
612      if (!sampler_view) {
613         pipe_resource_reference(&tex, NULL);
614         return;
615      }
616      pipe_resource_reference(&tex, NULL);
617   }
618   else {
619      /* Directly sample from the source resource/texture */
620      u_sampler_view_default_template(&sv_templ, src_tex, src_format);
621      if (!blit_depth && blit_stencil) {
622         /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
623         sv_templ.format = util_format_stencil_only(src_format);
624         assert(sv_templ.format != PIPE_FORMAT_NONE);
625      }
626      sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);
627
628      if (!sampler_view) {
629         return;
630      }
631
632      s0 = srcX0;
633      s1 = srcX1;
634      t0 = srcY0;
635      t1 = srcY1;
636      normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT;
637      if(normalized)
638      {
639         s0 /= (float)(u_minify(sampler_view->texture->width0, src_level));
640         s1 /= (float)(u_minify(sampler_view->texture->width0, src_level));
641         t0 /= (float)(u_minify(sampler_view->texture->height0, src_level));
642         t1 /= (float)(u_minify(sampler_view->texture->height0, src_level));
643      }
644   }
645
646   assert(screen->is_format_supported(screen, sampler_view->format,
647                     ctx->internal_target, sampler_view->texture->nr_samples,
648                     PIPE_BIND_SAMPLER_VIEW));
649   assert(screen->is_format_supported(screen, dst_format, ctx->internal_target,
650                     dst_surface->texture->nr_samples,
651                     is_depth || is_stencil ? PIPE_BIND_DEPTH_STENCIL :
652                                              PIPE_BIND_RENDER_TARGET));
653
654   /* save state (restored below) */
655   cso_save_blend(ctx->cso);
656   cso_save_depth_stencil_alpha(ctx->cso);
657   cso_save_rasterizer(ctx->cso);
658   cso_save_sample_mask(ctx->cso);
659   cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
660   cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
661   cso_save_stream_outputs(ctx->cso);
662   cso_save_viewport(ctx->cso);
663   cso_save_framebuffer(ctx->cso);
664   cso_save_fragment_shader(ctx->cso);
665   cso_save_vertex_shader(ctx->cso);
666   cso_save_geometry_shader(ctx->cso);
667   cso_save_vertex_elements(ctx->cso);
668   cso_save_vertex_buffers(ctx->cso);
669
670   /* set misc state we care about */
671   if (writemask)
672      cso_set_blend(ctx->cso, &ctx->blend_write_color);
673   else
674      cso_set_blend(ctx->cso, &ctx->blend_keep_color);
675
676   cso_set_sample_mask(ctx->cso, ~0);
677   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
678   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
679   cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
680
681   /* default sampler state */
682   ctx->sampler.normalized_coords = normalized;
683   ctx->sampler.min_img_filter = filter;
684   ctx->sampler.mag_img_filter = filter;
685   ctx->sampler.min_lod = src_level;
686   ctx->sampler.max_lod = src_level;
687
688   /* Depth stencil state, fragment shader and sampler setup depending on what
689    * we blit.
690    */
691   if (blit_depth && blit_stencil) {
692      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
693      /* don't filter stencil */
694      ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
695      ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
696      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &ctx->sampler);
697
698      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depthstencil);
699      set_depthstencil_fragment_shader(ctx, sampler_view->texture->target);
700   }
701   else if (blit_depth) {
702      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
703      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depth);
704      set_depth_fragment_shader(ctx, sampler_view->texture->target);
705   }
706   else if (blit_stencil) {
707      /* don't filter stencil */
708      ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
709      ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
710      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
711
712      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_stencil);
713      set_stencil_fragment_shader(ctx, sampler_view->texture->target);
714   }
715   else { /* color */
716      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
717      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
718      set_fragment_shader(ctx, writemask, sampler_view->texture->target);
719   }
720   cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);
721
722   /* textures */
723   if (blit_depth && blit_stencil) {
724      /* Setup two samplers, one for depth and the other one for stencil. */
725      struct pipe_sampler_view templ;
726      struct pipe_sampler_view *views[2];
727
728      templ = *sampler_view;
729      templ.format = util_format_stencil_only(templ.format);
730      assert(templ.format != PIPE_FORMAT_NONE);
731
732      views[0] = sampler_view;
733      views[1] = pipe->create_sampler_view(pipe, views[0]->texture, &templ);
734      cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 2, views);
735
736      pipe_sampler_view_reference(&views[1], NULL);
737   }
738   else {
739      cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &sampler_view);
740   }
741
742   /* viewport */
743   ctx->viewport.scale[0] = 0.5f * dst_surface->width;
744   ctx->viewport.scale[1] = 0.5f * dst_surface->height;
745   ctx->viewport.scale[2] = 0.5f;
746   ctx->viewport.scale[3] = 1.0f;
747   ctx->viewport.translate[0] = 0.5f * dst_surface->width;
748   ctx->viewport.translate[1] = 0.5f * dst_surface->height;
749   ctx->viewport.translate[2] = 0.5f;
750   ctx->viewport.translate[3] = 0.0f;
751   cso_set_viewport(ctx->cso, &ctx->viewport);
752
753   set_vertex_shader(ctx);
754   cso_set_geometry_shader_handle(ctx->cso, NULL);
755
756   /* drawing dest */
757   memset(&fb, 0, sizeof(fb));
758   fb.width = dst_surface->width;
759   fb.height = dst_surface->height;
760   if (blit_depth || blit_stencil) {
761      fb.zsbuf = dst_surface;
762   } else {
763      fb.nr_cbufs = 1;
764      fb.cbufs[0] = dst_surface;
765   }
766   cso_set_framebuffer(ctx->cso, &fb);
767
768   /* draw quad */
769   offset = setup_vertex_data_tex(ctx,
770                                  (float) dstX0 / dst_surface->width * 2.0f - 1.0f,
771                                  (float) dstY0 / dst_surface->height * 2.0f - 1.0f,
772                                  (float) dstX1 / dst_surface->width * 2.0f - 1.0f,
773                                  (float) dstY1 / dst_surface->height * 2.0f - 1.0f,
774                                  s0, t0,
775                                  s1, t1,
776                                  z);
777
778   if (ctx->vbuf) {
779      util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, offset,
780                              PIPE_PRIM_TRIANGLE_FAN,
781                              4,  /* verts */
782                              2); /* attribs/vert */
783   }
784
785   /* restore state we changed */
786   cso_restore_blend(ctx->cso);
787   cso_restore_depth_stencil_alpha(ctx->cso);
788   cso_restore_rasterizer(ctx->cso);
789   cso_restore_sample_mask(ctx->cso);
790   cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
791   cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
792   cso_restore_viewport(ctx->cso);
793   cso_restore_framebuffer(ctx->cso);
794   cso_restore_fragment_shader(ctx->cso);
795   cso_restore_vertex_shader(ctx->cso);
796   cso_restore_geometry_shader(ctx->cso);
797   cso_restore_vertex_elements(ctx->cso);
798   cso_restore_vertex_buffers(ctx->cso);
799   cso_restore_stream_outputs(ctx->cso);
800
801   pipe_sampler_view_reference(&sampler_view, NULL);
802   if (dst_surface != dst)
803      pipe_surface_reference(&dst_surface, NULL);
804}
805
806
807/**
808 * Copy pixel block from src texture to dst surface.
809 * The sampler view's first_level field indicates the source
810 * mipmap level to use.
811 * XXX need some control over blitting Z and/or stencil.
812 */
813void
814util_blit_pixels_tex(struct blit_state *ctx,
815                     struct pipe_sampler_view *src_sampler_view,
816                     int srcX0, int srcY0,
817                     int srcX1, int srcY1,
818                     struct pipe_surface *dst,
819                     int dstX0, int dstY0,
820                     int dstX1, int dstY1,
821                     float z, uint filter)
822{
823   boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
824   struct pipe_framebuffer_state fb;
825   float s0, t0, s1, t1;
826   unsigned offset;
827   struct pipe_resource *tex = src_sampler_view->texture;
828
829   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
830          filter == PIPE_TEX_MIPFILTER_LINEAR);
831
832   assert(tex);
833   assert(tex->width0 != 0);
834   assert(tex->height0 != 0);
835
836   s0 = srcX0;
837   s1 = srcX1;
838   t0 = srcY0;
839   t1 = srcY1;
840
841   if(normalized)
842   {
843      /* normalize according to the mipmap level's size */
844      int level = src_sampler_view->u.tex.first_level;
845      float w = (float) u_minify(tex->width0, level);
846      float h = (float) u_minify(tex->height0, level);
847      s0 /= w;
848      s1 /= w;
849      t0 /= h;
850      t1 /= h;
851   }
852
853   assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
854                                                 PIPE_TEXTURE_2D,
855                                                 dst->texture->nr_samples,
856                                                 PIPE_BIND_RENDER_TARGET));
857
858   /* save state (restored below) */
859   cso_save_blend(ctx->cso);
860   cso_save_depth_stencil_alpha(ctx->cso);
861   cso_save_rasterizer(ctx->cso);
862   cso_save_sample_mask(ctx->cso);
863   cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
864   cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
865   cso_save_stream_outputs(ctx->cso);
866   cso_save_viewport(ctx->cso);
867   cso_save_framebuffer(ctx->cso);
868   cso_save_fragment_shader(ctx->cso);
869   cso_save_vertex_shader(ctx->cso);
870   cso_save_geometry_shader(ctx->cso);
871   cso_save_vertex_elements(ctx->cso);
872   cso_save_vertex_buffers(ctx->cso);
873
874   /* set misc state we care about */
875   cso_set_blend(ctx->cso, &ctx->blend_write_color);
876   cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
877   cso_set_sample_mask(ctx->cso, ~0);
878   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
879   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
880   cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
881
882   /* sampler */
883   ctx->sampler.normalized_coords = normalized;
884   ctx->sampler.min_img_filter = filter;
885   ctx->sampler.mag_img_filter = filter;
886   cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
887   cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);
888
889   /* viewport */
890   ctx->viewport.scale[0] = 0.5f * dst->width;
891   ctx->viewport.scale[1] = 0.5f * dst->height;
892   ctx->viewport.scale[2] = 0.5f;
893   ctx->viewport.scale[3] = 1.0f;
894   ctx->viewport.translate[0] = 0.5f * dst->width;
895   ctx->viewport.translate[1] = 0.5f * dst->height;
896   ctx->viewport.translate[2] = 0.5f;
897   ctx->viewport.translate[3] = 0.0f;
898   cso_set_viewport(ctx->cso, &ctx->viewport);
899
900   /* texture */
901   cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &src_sampler_view);
902
903   /* shaders */
904   set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW,
905                       src_sampler_view->texture->target);
906   set_vertex_shader(ctx);
907   cso_set_geometry_shader_handle(ctx->cso, NULL);
908
909   /* drawing dest */
910   memset(&fb, 0, sizeof(fb));
911   fb.width = dst->width;
912   fb.height = dst->height;
913   fb.nr_cbufs = 1;
914   fb.cbufs[0] = dst;
915   cso_set_framebuffer(ctx->cso, &fb);
916
917   /* draw quad */
918   offset = setup_vertex_data_tex(ctx,
919                                  (float) dstX0 / dst->width * 2.0f - 1.0f,
920                                  (float) dstY0 / dst->height * 2.0f - 1.0f,
921                                  (float) dstX1 / dst->width * 2.0f - 1.0f,
922                                  (float) dstY1 / dst->height * 2.0f - 1.0f,
923                                  s0, t0, s1, t1,
924                                  z);
925
926   util_draw_vertex_buffer(ctx->pipe, ctx->cso,
927                           ctx->vbuf, offset,
928                           PIPE_PRIM_TRIANGLE_FAN,
929                           4,  /* verts */
930                           2); /* attribs/vert */
931
932   /* restore state we changed */
933   cso_restore_blend(ctx->cso);
934   cso_restore_depth_stencil_alpha(ctx->cso);
935   cso_restore_rasterizer(ctx->cso);
936   cso_restore_sample_mask(ctx->cso);
937   cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
938   cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
939   cso_restore_viewport(ctx->cso);
940   cso_restore_framebuffer(ctx->cso);
941   cso_restore_fragment_shader(ctx->cso);
942   cso_restore_vertex_shader(ctx->cso);
943   cso_restore_geometry_shader(ctx->cso);
944   cso_restore_vertex_elements(ctx->cso);
945   cso_restore_vertex_buffers(ctx->cso);
946   cso_restore_stream_outputs(ctx->cso);
947}
948