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