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