1848b8605Smrg/**************************************************************************
2848b8605Smrg *
3848b8605Smrg * Copyright 2008 VMware, Inc.
4848b8605Smrg * All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the
8848b8605Smrg * "Software"), to deal in the Software without restriction, including
9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish,
10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to
11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to
12848b8605Smrg * the following conditions:
13848b8605Smrg *
14848b8605Smrg * The above copyright notice and this permission notice (including the
15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions
16848b8605Smrg * of the Software.
17848b8605Smrg *
18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25848b8605Smrg *
26848b8605Smrg **************************************************************************/
27848b8605Smrg
28848b8605Smrg/**
29848b8605Smrg * @file
30848b8605Smrg * Copy/blit pixel rect between surfaces
31b8e80941Smrg *
32848b8605Smrg * @author Brian Paul
33848b8605Smrg */
34848b8605Smrg
35848b8605Smrg
36848b8605Smrg#include "pipe/p_context.h"
37848b8605Smrg#include "util/u_debug.h"
38848b8605Smrg#include "pipe/p_defines.h"
39848b8605Smrg#include "util/u_inlines.h"
40848b8605Smrg#include "pipe/p_shader_tokens.h"
41848b8605Smrg#include "pipe/p_state.h"
42848b8605Smrg
43848b8605Smrg#include "util/u_blit.h"
44848b8605Smrg#include "util/u_draw_quad.h"
45848b8605Smrg#include "util/u_format.h"
46848b8605Smrg#include "util/u_math.h"
47848b8605Smrg#include "util/u_memory.h"
48848b8605Smrg#include "util/u_sampler.h"
49848b8605Smrg#include "util/u_texture.h"
50848b8605Smrg#include "util/u_simple_shaders.h"
51848b8605Smrg
52848b8605Smrg#include "cso_cache/cso_context.h"
53848b8605Smrg
54848b8605Smrg
55848b8605Smrgstruct blit_state
56848b8605Smrg{
57848b8605Smrg   struct pipe_context *pipe;
58848b8605Smrg   struct cso_context *cso;
59848b8605Smrg
60848b8605Smrg   struct pipe_blend_state blend_write_color;
61848b8605Smrg   struct pipe_depth_stencil_alpha_state dsa_keep_depthstencil;
62848b8605Smrg   struct pipe_rasterizer_state rasterizer;
63848b8605Smrg   struct pipe_sampler_state sampler;
64848b8605Smrg   struct pipe_viewport_state viewport;
65848b8605Smrg   struct pipe_vertex_element velem[2];
66848b8605Smrg
67848b8605Smrg   void *vs;
68b8e80941Smrg   void *fs[PIPE_MAX_TEXTURE_TYPES][4];
69848b8605Smrg
70848b8605Smrg   struct pipe_resource *vbuf;  /**< quad vertices */
71848b8605Smrg   unsigned vbuf_slot;
72848b8605Smrg
73848b8605Smrg   float vertices[4][2][4];   /**< vertex/texcoords for quad */
74848b8605Smrg};
75848b8605Smrg
76848b8605Smrg
77848b8605Smrg/**
78848b8605Smrg * Create state object for blit.
79848b8605Smrg * Intended to be created once and re-used for many blit() calls.
80848b8605Smrg */
81848b8605Smrgstruct blit_state *
82848b8605Smrgutil_create_blit(struct pipe_context *pipe, struct cso_context *cso)
83848b8605Smrg{
84848b8605Smrg   struct blit_state *ctx;
85848b8605Smrg   uint i;
86848b8605Smrg
87848b8605Smrg   ctx = CALLOC_STRUCT(blit_state);
88848b8605Smrg   if (!ctx)
89848b8605Smrg      return NULL;
90848b8605Smrg
91848b8605Smrg   ctx->pipe = pipe;
92848b8605Smrg   ctx->cso = cso;
93848b8605Smrg
94848b8605Smrg   /* disabled blending/masking */
95848b8605Smrg   ctx->blend_write_color.rt[0].colormask = PIPE_MASK_RGBA;
96848b8605Smrg
97848b8605Smrg   /* rasterizer */
98848b8605Smrg   ctx->rasterizer.cull_face = PIPE_FACE_NONE;
99848b8605Smrg   ctx->rasterizer.half_pixel_center = 1;
100848b8605Smrg   ctx->rasterizer.bottom_edge_rule = 1;
101b8e80941Smrg   ctx->rasterizer.depth_clip_near = 1;
102b8e80941Smrg   ctx->rasterizer.depth_clip_far = 1;
103848b8605Smrg
104848b8605Smrg   /* samplers */
105848b8605Smrg   ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
106848b8605Smrg   ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
107848b8605Smrg   ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
108848b8605Smrg   ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
109848b8605Smrg   ctx->sampler.min_img_filter = 0; /* set later */
110848b8605Smrg   ctx->sampler.mag_img_filter = 0; /* set later */
111848b8605Smrg
112848b8605Smrg   /* vertex elements state */
113848b8605Smrg   for (i = 0; i < 2; i++) {
114848b8605Smrg      ctx->velem[i].src_offset = i * 4 * sizeof(float);
115848b8605Smrg      ctx->velem[i].instance_divisor = 0;
116b8e80941Smrg      ctx->velem[i].vertex_buffer_index = 0;
117848b8605Smrg      ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
118848b8605Smrg   }
119848b8605Smrg
120848b8605Smrg   ctx->vbuf = NULL;
121848b8605Smrg
122848b8605Smrg   /* init vertex data that doesn't change */
123848b8605Smrg   for (i = 0; i < 4; i++) {
124848b8605Smrg      ctx->vertices[i][0][3] = 1.0f; /* w */
125848b8605Smrg      ctx->vertices[i][1][3] = 1.0f; /* q */
126848b8605Smrg   }
127848b8605Smrg
128848b8605Smrg   return ctx;
129848b8605Smrg}
130848b8605Smrg
131848b8605Smrg
132848b8605Smrg/**
133848b8605Smrg * Destroy a blit context
134848b8605Smrg */
135848b8605Smrgvoid
136848b8605Smrgutil_destroy_blit(struct blit_state *ctx)
137848b8605Smrg{
138848b8605Smrg   struct pipe_context *pipe = ctx->pipe;
139848b8605Smrg   unsigned i, j;
140848b8605Smrg
141848b8605Smrg   if (ctx->vs)
142848b8605Smrg      pipe->delete_vs_state(pipe, ctx->vs);
143848b8605Smrg
144b8e80941Smrg   for (i = 0; i < ARRAY_SIZE(ctx->fs); i++) {
145b8e80941Smrg      for (j = 0; j < ARRAY_SIZE(ctx->fs[i]); j++) {
146848b8605Smrg         if (ctx->fs[i][j])
147848b8605Smrg            pipe->delete_fs_state(pipe, ctx->fs[i][j]);
148848b8605Smrg      }
149848b8605Smrg   }
150848b8605Smrg
151848b8605Smrg   pipe_resource_reference(&ctx->vbuf, NULL);
152848b8605Smrg
153848b8605Smrg   FREE(ctx);
154848b8605Smrg}
155848b8605Smrg
156848b8605Smrg
157848b8605Smrg/**
158848b8605Smrg * Helper function to set the fragment shaders.
159848b8605Smrg */
160b8e80941Smrgstatic inline void
161b8e80941Smrgset_fragment_shader(struct blit_state *ctx,
162b8e80941Smrg                    enum pipe_format format,
163b8e80941Smrg                    boolean src_xrbias,
164848b8605Smrg                    enum pipe_texture_target pipe_tex)
165848b8605Smrg{
166b8e80941Smrg   enum tgsi_return_type stype;
167b8e80941Smrg   unsigned idx;
168b8e80941Smrg
169b8e80941Smrg   if (util_format_is_pure_uint(format)) {
170b8e80941Smrg      stype = TGSI_RETURN_TYPE_UINT;
171b8e80941Smrg      idx = 0;
172b8e80941Smrg   } else if (util_format_is_pure_sint(format)) {
173b8e80941Smrg      stype = TGSI_RETURN_TYPE_SINT;
174b8e80941Smrg      idx = 1;
175b8e80941Smrg   } else {
176b8e80941Smrg      stype = TGSI_RETURN_TYPE_FLOAT;
177b8e80941Smrg      idx = 2;
178b8e80941Smrg   }
179b8e80941Smrg
180b8e80941Smrg   if (src_xrbias) {
181b8e80941Smrg      assert(stype == TGSI_RETURN_TYPE_FLOAT);
182b8e80941Smrg      idx = 3;
183b8e80941Smrg      if (!ctx->fs[pipe_tex][idx]) {
184b8e80941Smrg         enum tgsi_texture_type tgsi_tex =
185b8e80941Smrg            util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
186b8e80941Smrg         ctx->fs[pipe_tex][idx] =
187b8e80941Smrg            util_make_fragment_tex_shader_xrbias(ctx->pipe, tgsi_tex);
188b8e80941Smrg      }
189b8e80941Smrg   }
190b8e80941Smrg   else if (!ctx->fs[pipe_tex][idx]) {
191b8e80941Smrg      enum tgsi_texture_type tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
192848b8605Smrg
193b8e80941Smrg      /* OpenGL does not allow blits from signed to unsigned integer
194b8e80941Smrg       * or vice versa. */
195b8e80941Smrg      ctx->fs[pipe_tex][idx] =
196848b8605Smrg         util_make_fragment_tex_shader_writemask(ctx->pipe, tgsi_tex,
197848b8605Smrg                                                 TGSI_INTERPOLATE_LINEAR,
198b8e80941Smrg                                                 TGSI_WRITEMASK_XYZW,
199b8e80941Smrg                                                 stype, stype, false, false);
200848b8605Smrg   }
201848b8605Smrg
202b8e80941Smrg   cso_set_fragment_shader_handle(ctx->cso, ctx->fs[pipe_tex][idx]);
203848b8605Smrg}
204848b8605Smrg
205848b8605Smrg
206848b8605Smrg/**
207848b8605Smrg * Helper function to set the vertex shader.
208848b8605Smrg */
209b8e80941Smrgstatic inline void
210848b8605Smrgset_vertex_shader(struct blit_state *ctx)
211848b8605Smrg{
212848b8605Smrg   /* vertex shader - still required to provide the linkage between
213848b8605Smrg    * fragment shader input semantics and vertex_element/buffers.
214848b8605Smrg    */
215848b8605Smrg   if (!ctx->vs) {
216b8e80941Smrg      const enum tgsi_semantic semantic_names[] = {
217b8e80941Smrg         TGSI_SEMANTIC_POSITION,
218b8e80941Smrg         TGSI_SEMANTIC_GENERIC
219b8e80941Smrg      };
220848b8605Smrg      const uint semantic_indexes[] = { 0, 0 };
221848b8605Smrg      ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2,
222848b8605Smrg                                                    semantic_names,
223b8e80941Smrg                                                    semantic_indexes, FALSE);
224848b8605Smrg   }
225848b8605Smrg
226848b8605Smrg   cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
227848b8605Smrg}
228848b8605Smrg
229848b8605Smrg
230848b8605Smrg/**
231848b8605Smrg * Get offset of next free slot in vertex buffer for quad vertices.
232848b8605Smrg */
233848b8605Smrgstatic unsigned
234b8e80941Smrgget_next_slot(struct blit_state *ctx)
235848b8605Smrg{
236848b8605Smrg   const unsigned max_slots = 4096 / sizeof ctx->vertices;
237848b8605Smrg
238848b8605Smrg   if (ctx->vbuf_slot >= max_slots) {
239848b8605Smrg      pipe_resource_reference(&ctx->vbuf, NULL);
240848b8605Smrg      ctx->vbuf_slot = 0;
241848b8605Smrg   }
242848b8605Smrg
243848b8605Smrg   if (!ctx->vbuf) {
244848b8605Smrg      ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
245848b8605Smrg                                     PIPE_BIND_VERTEX_BUFFER,
246848b8605Smrg                                     PIPE_USAGE_STREAM,
247848b8605Smrg                                     max_slots * sizeof ctx->vertices);
248848b8605Smrg   }
249b8e80941Smrg
250848b8605Smrg   return ctx->vbuf_slot++ * sizeof ctx->vertices;
251848b8605Smrg}
252848b8605Smrg
253848b8605Smrg
254848b8605Smrg
255848b8605Smrg
256848b8605Smrg/**
257848b8605Smrg * Setup vertex data for the textured quad we'll draw.
258848b8605Smrg * Note: y=0=top
259848b8605Smrg *
260848b8605Smrg * FIXME: We should call util_map_texcoords2d_onto_cubemap
261848b8605Smrg * for cubemaps.
262848b8605Smrg */
263848b8605Smrgstatic unsigned
264848b8605Smrgsetup_vertex_data_tex(struct blit_state *ctx,
265b8e80941Smrg                      enum pipe_texture_target src_target,
266848b8605Smrg                      unsigned src_face,
267848b8605Smrg                      float x0, float y0, float x1, float y1,
268848b8605Smrg                      float s0, float t0, float s1, float t1,
269848b8605Smrg                      float z)
270848b8605Smrg{
271848b8605Smrg   unsigned offset;
272848b8605Smrg
273848b8605Smrg   ctx->vertices[0][0][0] = x0;
274848b8605Smrg   ctx->vertices[0][0][1] = y0;
275848b8605Smrg   ctx->vertices[0][0][2] = z;
276848b8605Smrg   ctx->vertices[0][1][0] = s0; /*s*/
277848b8605Smrg   ctx->vertices[0][1][1] = t0; /*t*/
278848b8605Smrg   ctx->vertices[0][1][2] = 0;  /*r*/
279848b8605Smrg
280848b8605Smrg   ctx->vertices[1][0][0] = x1;
281848b8605Smrg   ctx->vertices[1][0][1] = y0;
282848b8605Smrg   ctx->vertices[1][0][2] = z;
283848b8605Smrg   ctx->vertices[1][1][0] = s1; /*s*/
284848b8605Smrg   ctx->vertices[1][1][1] = t0; /*t*/
285848b8605Smrg   ctx->vertices[1][1][2] = 0;  /*r*/
286848b8605Smrg
287848b8605Smrg   ctx->vertices[2][0][0] = x1;
288848b8605Smrg   ctx->vertices[2][0][1] = y1;
289848b8605Smrg   ctx->vertices[2][0][2] = z;
290848b8605Smrg   ctx->vertices[2][1][0] = s1;
291848b8605Smrg   ctx->vertices[2][1][1] = t1;
292848b8605Smrg   ctx->vertices[3][1][2] = 0;
293848b8605Smrg
294848b8605Smrg   ctx->vertices[3][0][0] = x0;
295848b8605Smrg   ctx->vertices[3][0][1] = y1;
296848b8605Smrg   ctx->vertices[3][0][2] = z;
297848b8605Smrg   ctx->vertices[3][1][0] = s0;
298848b8605Smrg   ctx->vertices[3][1][1] = t1;
299848b8605Smrg   ctx->vertices[3][1][2] = 0;
300848b8605Smrg
301848b8605Smrg   if (src_target == PIPE_TEXTURE_CUBE ||
302848b8605Smrg       src_target == PIPE_TEXTURE_CUBE_ARRAY) {
303848b8605Smrg      /* Map cubemap texture coordinates inplace. */
304b8e80941Smrg      const unsigned stride =
305b8e80941Smrg         sizeof ctx->vertices[0] / sizeof ctx->vertices[0][0][0];
306848b8605Smrg      util_map_texcoords2d_onto_cubemap(src_face,
307848b8605Smrg                                        &ctx->vertices[0][1][0], stride,
308848b8605Smrg                                        &ctx->vertices[0][1][0], stride,
309848b8605Smrg                                        TRUE);
310848b8605Smrg   }
311848b8605Smrg
312b8e80941Smrg   offset = get_next_slot(ctx);
313848b8605Smrg
314848b8605Smrg   if (ctx->vbuf) {
315848b8605Smrg      pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf,
316848b8605Smrg                                  offset, sizeof(ctx->vertices), ctx->vertices);
317848b8605Smrg   }
318848b8605Smrg
319848b8605Smrg   return offset;
320848b8605Smrg}
321848b8605Smrg
322848b8605Smrg
323848b8605Smrg/**
324848b8605Smrg * \return TRUE if two regions overlap, FALSE otherwise
325848b8605Smrg */
326848b8605Smrgstatic boolean
327848b8605Smrgregions_overlap(int srcX0, int srcY0,
328848b8605Smrg                int srcX1, int srcY1,
329848b8605Smrg                int dstX0, int dstY0,
330848b8605Smrg                int dstX1, int dstY1)
331848b8605Smrg{
332b8e80941Smrg   if (MAX2(srcX0, srcX1) <= MIN2(dstX0, dstX1))
333848b8605Smrg      return FALSE; /* src completely left of dst */
334848b8605Smrg
335b8e80941Smrg   if (MAX2(dstX0, dstX1) <= MIN2(srcX0, srcX1))
336848b8605Smrg      return FALSE; /* dst completely left of src */
337848b8605Smrg
338b8e80941Smrg   if (MAX2(srcY0, srcY1) <= MIN2(dstY0, dstY1))
339848b8605Smrg      return FALSE; /* src completely above dst */
340848b8605Smrg
341b8e80941Smrg   if (MAX2(dstY0, dstY1) <= MIN2(srcY0, srcY1))
342848b8605Smrg      return FALSE; /* dst completely above src */
343848b8605Smrg
344848b8605Smrg   return TRUE; /* some overlap */
345848b8605Smrg}
346848b8605Smrg
347848b8605Smrg
348848b8605Smrg/**
349848b8605Smrg * Can we blit from src format to dest format with a simple copy?
350848b8605Smrg */
351848b8605Smrgstatic boolean
352848b8605Smrgformats_compatible(enum pipe_format src_format,
353848b8605Smrg                   enum pipe_format dst_format)
354848b8605Smrg{
355848b8605Smrg   if (src_format == dst_format) {
356848b8605Smrg      return TRUE;
357848b8605Smrg   }
358848b8605Smrg   else {
359848b8605Smrg      const struct util_format_description *src_desc =
360848b8605Smrg         util_format_description(src_format);
361848b8605Smrg      const struct util_format_description *dst_desc =
362848b8605Smrg         util_format_description(dst_format);
363848b8605Smrg      return util_is_format_compatible(src_desc, dst_desc);
364848b8605Smrg   }
365848b8605Smrg}
366848b8605Smrg
367848b8605Smrg
368848b8605Smrg/**
369848b8605Smrg * Copy pixel block from src surface to dst surface.
370848b8605Smrg * Overlapping regions are acceptable.
371848b8605Smrg * Flipping and stretching are supported.
372b8e80941Smrg * \param filter  one of PIPE_TEX_FILTER_NEAREST/LINEAR
373b8e80941Smrg * \param writemask  bitmask of PIPE_MASK_[RGBAZS].  Controls which channels
374b8e80941Smrg *                   in the dest surface are sourced from the src surface.
375b8e80941Smrg *                   Disabled color channels are sourced from (0,0,0,1).
376848b8605Smrg */
377848b8605Smrgvoid
378848b8605Smrgutil_blit_pixels(struct blit_state *ctx,
379848b8605Smrg                 struct pipe_resource *src_tex,
380848b8605Smrg                 unsigned src_level,
381848b8605Smrg                 int srcX0, int srcY0,
382848b8605Smrg                 int srcX1, int srcY1,
383848b8605Smrg                 int srcZ0,
384848b8605Smrg                 struct pipe_surface *dst,
385848b8605Smrg                 int dstX0, int dstY0,
386848b8605Smrg                 int dstX1, int dstY1,
387b8e80941Smrg                 MAYBE_UNUSED float z,
388b8e80941Smrg                 enum pipe_tex_filter filter,
389b8e80941Smrg                 uint writemask)
390848b8605Smrg{
391848b8605Smrg   struct pipe_context *pipe = ctx->pipe;
392848b8605Smrg   enum pipe_format src_format, dst_format;
393848b8605Smrg   const int srcW = abs(srcX1 - srcX0);
394848b8605Smrg   const int srcH = abs(srcY1 - srcY0);
395848b8605Smrg   boolean overlap;
396848b8605Smrg   boolean is_stencil, is_depth, blit_depth, blit_stencil;
397848b8605Smrg   const struct util_format_description *src_desc =
398848b8605Smrg         util_format_description(src_tex->format);
399848b8605Smrg   struct pipe_blit_info info;
400848b8605Smrg
401b8e80941Smrg   assert(filter == PIPE_TEX_FILTER_NEAREST ||
402b8e80941Smrg          filter == PIPE_TEX_FILTER_LINEAR);
403848b8605Smrg
404848b8605Smrg   assert(src_level <= src_tex->last_level);
405848b8605Smrg
406848b8605Smrg   /* do the regions overlap? */
407848b8605Smrg   overlap = src_tex == dst->texture &&
408848b8605Smrg             dst->u.tex.level == src_level &&
409848b8605Smrg             dst->u.tex.first_layer == srcZ0 &&
410848b8605Smrg      regions_overlap(srcX0, srcY0, srcX1, srcY1,
411848b8605Smrg                      dstX0, dstY0, dstX1, dstY1);
412848b8605Smrg
413848b8605Smrg   src_format = util_format_linear(src_tex->format);
414848b8605Smrg   dst_format = util_format_linear(dst->texture->format);
415848b8605Smrg
416848b8605Smrg   /* See whether we will blit depth or stencil. */
417848b8605Smrg   is_depth = util_format_has_depth(src_desc);
418848b8605Smrg   is_stencil = util_format_has_stencil(src_desc);
419848b8605Smrg
420b8e80941Smrg   blit_depth = is_depth && (writemask & PIPE_MASK_Z);
421b8e80941Smrg   blit_stencil = is_stencil && (writemask & PIPE_MASK_S);
422848b8605Smrg
423b8e80941Smrg   if (is_depth || is_stencil) {
424b8e80941Smrg      assert((writemask & PIPE_MASK_RGBA) == 0);
425b8e80941Smrg      assert(blit_depth || blit_stencil);
426b8e80941Smrg   }
427b8e80941Smrg   else {
428b8e80941Smrg      assert((writemask & PIPE_MASK_ZS) == 0);
429b8e80941Smrg      assert(!blit_depth);
430b8e80941Smrg      assert(!blit_stencil);
431b8e80941Smrg   }
432848b8605Smrg
433848b8605Smrg   /*
434848b8605Smrg    * XXX: z parameter is deprecated. dst->u.tex.first_layer
435848b8605Smrg    * specificies the destination layer.
436848b8605Smrg    */
437848b8605Smrg   assert(z == 0.0f);
438848b8605Smrg
439848b8605Smrg   /*
440848b8605Smrg    * Check for simple case:  no format conversion, no flipping, no stretching,
441848b8605Smrg    * no overlapping, same number of samples.
442848b8605Smrg    * Filter mode should not matter since there's no stretching.
443848b8605Smrg    */
444848b8605Smrg   if (formats_compatible(src_format, dst_format) &&
445848b8605Smrg       src_tex->nr_samples == dst->texture->nr_samples &&
446848b8605Smrg       is_stencil == blit_stencil &&
447848b8605Smrg       is_depth == blit_depth &&
448848b8605Smrg       srcX0 < srcX1 &&
449848b8605Smrg       dstX0 < dstX1 &&
450848b8605Smrg       srcY0 < srcY1 &&
451848b8605Smrg       dstY0 < dstY1 &&
452848b8605Smrg       (dstX1 - dstX0) == (srcX1 - srcX0) &&
453848b8605Smrg       (dstY1 - dstY0) == (srcY1 - srcY0) &&
454848b8605Smrg       !overlap) {
455848b8605Smrg      struct pipe_box src_box;
456848b8605Smrg      src_box.x = srcX0;
457848b8605Smrg      src_box.y = srcY0;
458848b8605Smrg      src_box.z = srcZ0;
459848b8605Smrg      src_box.width = srcW;
460848b8605Smrg      src_box.height = srcH;
461848b8605Smrg      src_box.depth = 1;
462848b8605Smrg      pipe->resource_copy_region(pipe,
463848b8605Smrg                                 dst->texture, dst->u.tex.level,
464848b8605Smrg                                 dstX0, dstY0, dst->u.tex.first_layer,/* dest */
465848b8605Smrg                                 src_tex, src_level,
466848b8605Smrg                                 &src_box);
467848b8605Smrg      return;
468848b8605Smrg   }
469848b8605Smrg
470848b8605Smrg   memset(&info, 0, sizeof info);
471848b8605Smrg   info.dst.resource = dst->texture;
472848b8605Smrg   info.dst.level = dst->u.tex.level;
473848b8605Smrg   info.dst.box.x = dstX0;
474848b8605Smrg   info.dst.box.y = dstY0;
475848b8605Smrg   info.dst.box.z = dst->u.tex.first_layer;
476848b8605Smrg   info.dst.box.width = dstX1 - dstX0;
477848b8605Smrg   info.dst.box.height = dstY1 - dstY0;
478848b8605Smrg   assert(info.dst.box.width >= 0);
479848b8605Smrg   assert(info.dst.box.height >= 0);
480848b8605Smrg   info.dst.box.depth = 1;
481b8e80941Smrg   info.dst.format = dst_format;
482848b8605Smrg   info.src.resource = src_tex;
483848b8605Smrg   info.src.level = src_level;
484848b8605Smrg   info.src.box.x = srcX0;
485848b8605Smrg   info.src.box.y = srcY0;
486848b8605Smrg   info.src.box.z = srcZ0;
487848b8605Smrg   info.src.box.width = srcX1 - srcX0;
488848b8605Smrg   info.src.box.height = srcY1 - srcY0;
489848b8605Smrg   info.src.box.depth = 1;
490b8e80941Smrg   info.src.format = src_format;
491b8e80941Smrg   info.mask = writemask;
492848b8605Smrg   info.filter = filter;
493848b8605Smrg   info.scissor_enable = 0;
494848b8605Smrg
495848b8605Smrg   pipe->blit(pipe, &info);
496848b8605Smrg}
497848b8605Smrg
498848b8605Smrg
499848b8605Smrg/**
500848b8605Smrg * Copy pixel block from src sampler view to dst surface.
501848b8605Smrg *
502848b8605Smrg * The sampler view's first_level field indicates the source
503848b8605Smrg * mipmap level to use.
504848b8605Smrg *
505848b8605Smrg * The sampler view's first_layer indicate the layer to use, but for
506848b8605Smrg * cube maps it must point to the first face.  Face is passed in src_face.
507848b8605Smrg *
508b8e80941Smrg * The main advantage over util_blit_pixels is that it allows to specify
509b8e80941Smrg * swizzles in pipe_sampler_view::swizzle_?.
510848b8605Smrg *
511848b8605Smrg * But there is no control over blitting Z and/or stencil.
512848b8605Smrg */
513848b8605Smrgvoid
514848b8605Smrgutil_blit_pixels_tex(struct blit_state *ctx,
515848b8605Smrg                     struct pipe_sampler_view *src_sampler_view,
516848b8605Smrg                     int srcX0, int srcY0,
517848b8605Smrg                     int srcX1, int srcY1,
518848b8605Smrg                     unsigned src_face,
519848b8605Smrg                     struct pipe_surface *dst,
520848b8605Smrg                     int dstX0, int dstY0,
521848b8605Smrg                     int dstX1, int dstY1,
522b8e80941Smrg                     float z, enum pipe_tex_filter filter,
523b8e80941Smrg                     boolean src_xrbias)
524848b8605Smrg{
525848b8605Smrg   boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
526848b8605Smrg   struct pipe_framebuffer_state fb;
527848b8605Smrg   float s0, t0, s1, t1;
528848b8605Smrg   unsigned offset;
529848b8605Smrg   struct pipe_resource *tex = src_sampler_view->texture;
530848b8605Smrg
531b8e80941Smrg   assert(filter == PIPE_TEX_FILTER_NEAREST ||
532b8e80941Smrg          filter == PIPE_TEX_FILTER_LINEAR);
533848b8605Smrg
534848b8605Smrg   assert(tex);
535848b8605Smrg   assert(tex->width0 != 0);
536848b8605Smrg   assert(tex->height0 != 0);
537848b8605Smrg
538848b8605Smrg   s0 = (float) srcX0;
539848b8605Smrg   s1 = (float) srcX1;
540848b8605Smrg   t0 = (float) srcY0;
541848b8605Smrg   t1 = (float) srcY1;
542848b8605Smrg
543b8e80941Smrg   if (normalized) {
544848b8605Smrg      /* normalize according to the mipmap level's size */
545848b8605Smrg      int level = src_sampler_view->u.tex.first_level;
546848b8605Smrg      float w = (float) u_minify(tex->width0, level);
547848b8605Smrg      float h = (float) u_minify(tex->height0, level);
548848b8605Smrg      s0 /= w;
549848b8605Smrg      s1 /= w;
550848b8605Smrg      t0 /= h;
551848b8605Smrg      t1 /= h;
552848b8605Smrg   }
553848b8605Smrg
554848b8605Smrg   assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
555848b8605Smrg                                                 PIPE_TEXTURE_2D,
556848b8605Smrg                                                 dst->texture->nr_samples,
557b8e80941Smrg                                                 dst->texture->nr_storage_samples,
558848b8605Smrg                                                 PIPE_BIND_RENDER_TARGET));
559848b8605Smrg
560848b8605Smrg   /* save state (restored below) */
561b8e80941Smrg   cso_save_state(ctx->cso, (CSO_BIT_BLEND |
562b8e80941Smrg                             CSO_BIT_DEPTH_STENCIL_ALPHA |
563b8e80941Smrg                             CSO_BIT_RASTERIZER |
564b8e80941Smrg                             CSO_BIT_SAMPLE_MASK |
565b8e80941Smrg                             CSO_BIT_MIN_SAMPLES |
566b8e80941Smrg                             CSO_BIT_FRAGMENT_SAMPLERS |
567b8e80941Smrg                             CSO_BIT_FRAGMENT_SAMPLER_VIEWS |
568b8e80941Smrg                             CSO_BIT_STREAM_OUTPUTS |
569b8e80941Smrg                             CSO_BIT_VIEWPORT |
570b8e80941Smrg                             CSO_BIT_FRAMEBUFFER |
571b8e80941Smrg                             CSO_BIT_PAUSE_QUERIES |
572b8e80941Smrg                             CSO_BIT_FRAGMENT_SHADER |
573b8e80941Smrg                             CSO_BIT_VERTEX_SHADER |
574b8e80941Smrg                             CSO_BIT_TESSCTRL_SHADER |
575b8e80941Smrg                             CSO_BIT_TESSEVAL_SHADER |
576b8e80941Smrg                             CSO_BIT_GEOMETRY_SHADER |
577b8e80941Smrg                             CSO_BIT_VERTEX_ELEMENTS |
578b8e80941Smrg                             CSO_BIT_AUX_VERTEX_BUFFER_SLOT));
579848b8605Smrg
580848b8605Smrg   /* set misc state we care about */
581848b8605Smrg   cso_set_blend(ctx->cso, &ctx->blend_write_color);
582848b8605Smrg   cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
583848b8605Smrg   cso_set_sample_mask(ctx->cso, ~0);
584848b8605Smrg   cso_set_min_samples(ctx->cso, 1);
585848b8605Smrg   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
586848b8605Smrg   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
587848b8605Smrg   cso_set_stream_outputs(ctx->cso, 0, NULL, NULL);
588848b8605Smrg
589848b8605Smrg   /* sampler */
590848b8605Smrg   ctx->sampler.normalized_coords = normalized;
591848b8605Smrg   ctx->sampler.min_img_filter = filter;
592848b8605Smrg   ctx->sampler.mag_img_filter = filter;
593b8e80941Smrg   {
594b8e80941Smrg      const struct pipe_sampler_state *samplers[] = {&ctx->sampler};
595b8e80941Smrg      cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, 1, samplers);
596b8e80941Smrg   }
597848b8605Smrg
598848b8605Smrg   /* viewport */
599848b8605Smrg   ctx->viewport.scale[0] = 0.5f * dst->width;
600848b8605Smrg   ctx->viewport.scale[1] = 0.5f * dst->height;
601848b8605Smrg   ctx->viewport.scale[2] = 0.5f;
602848b8605Smrg   ctx->viewport.translate[0] = 0.5f * dst->width;
603848b8605Smrg   ctx->viewport.translate[1] = 0.5f * dst->height;
604848b8605Smrg   ctx->viewport.translate[2] = 0.5f;
605848b8605Smrg   cso_set_viewport(ctx->cso, &ctx->viewport);
606848b8605Smrg
607848b8605Smrg   /* texture */
608848b8605Smrg   cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &src_sampler_view);
609848b8605Smrg
610848b8605Smrg   /* shaders */
611b8e80941Smrg   set_fragment_shader(ctx, src_sampler_view->format,
612b8e80941Smrg                       src_xrbias,
613848b8605Smrg                       src_sampler_view->texture->target);
614848b8605Smrg   set_vertex_shader(ctx);
615b8e80941Smrg   cso_set_tessctrl_shader_handle(ctx->cso, NULL);
616b8e80941Smrg   cso_set_tesseval_shader_handle(ctx->cso, NULL);
617848b8605Smrg   cso_set_geometry_shader_handle(ctx->cso, NULL);
618848b8605Smrg
619848b8605Smrg   /* drawing dest */
620848b8605Smrg   memset(&fb, 0, sizeof(fb));
621848b8605Smrg   fb.width = dst->width;
622848b8605Smrg   fb.height = dst->height;
623848b8605Smrg   fb.nr_cbufs = 1;
624848b8605Smrg   fb.cbufs[0] = dst;
625848b8605Smrg   cso_set_framebuffer(ctx->cso, &fb);
626848b8605Smrg
627848b8605Smrg   /* draw quad */
628848b8605Smrg   offset = setup_vertex_data_tex(ctx,
629848b8605Smrg                                  src_sampler_view->texture->target,
630848b8605Smrg                                  src_face,
631848b8605Smrg                                  (float) dstX0 / dst->width * 2.0f - 1.0f,
632848b8605Smrg                                  (float) dstY0 / dst->height * 2.0f - 1.0f,
633848b8605Smrg                                  (float) dstX1 / dst->width * 2.0f - 1.0f,
634848b8605Smrg                                  (float) dstY1 / dst->height * 2.0f - 1.0f,
635848b8605Smrg                                  s0, t0, s1, t1,
636848b8605Smrg                                  z);
637848b8605Smrg
638b8e80941Smrg   util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, 0,
639848b8605Smrg                           offset,
640848b8605Smrg                           PIPE_PRIM_TRIANGLE_FAN,
641848b8605Smrg                           4,  /* verts */
642848b8605Smrg                           2); /* attribs/vert */
643848b8605Smrg
644848b8605Smrg   /* restore state we changed */
645b8e80941Smrg   cso_restore_state(ctx->cso);
646848b8605Smrg}
647