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