2 * Copyright (C) 2017 Rob Clark <robclark@freedesktop.org>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * Rob Clark <robclark@freedesktop.org>
27 #include "util/u_blitter.h"
28 #include "util/u_surface.h"
30 #include "freedreno_blitter.h"
31 #include "freedreno_context.h"
32 #include "freedreno_resource.h"
34 /* generic blit using u_blitter.. slightly modified version of util_blitter_blit
35 * which also handles PIPE_BUFFER:
39 default_dst_texture(struct pipe_surface
*dst_templ
, struct pipe_resource
*dst
,
40 unsigned dstlevel
, unsigned dstz
)
42 memset(dst_templ
, 0, sizeof(*dst_templ
));
43 if (dst
->target
== PIPE_BUFFER
)
44 dst_templ
->format
= PIPE_FORMAT_R8_UINT
;
46 dst_templ
->format
= util_format_linear(dst
->format
);
47 dst_templ
->u
.tex
.level
= dstlevel
;
48 dst_templ
->u
.tex
.first_layer
= dstz
;
49 dst_templ
->u
.tex
.last_layer
= dstz
;
53 default_src_texture(struct pipe_sampler_view
*src_templ
,
54 struct pipe_resource
*src
, unsigned srclevel
)
56 bool cube_as_2darray
= src
->screen
->get_param(src
->screen
,
57 PIPE_CAP_SAMPLER_VIEW_TARGET
);
59 memset(src_templ
, 0, sizeof(*src_templ
));
61 if (cube_as_2darray
&& (src
->target
== PIPE_TEXTURE_CUBE
||
62 src
->target
== PIPE_TEXTURE_CUBE_ARRAY
))
63 src_templ
->target
= PIPE_TEXTURE_2D_ARRAY
;
65 src_templ
->target
= src
->target
;
67 if (src
->target
== PIPE_BUFFER
) {
68 src_templ
->target
= PIPE_TEXTURE_1D
;
69 src_templ
->format
= PIPE_FORMAT_R8_UINT
;
71 src_templ
->format
= util_format_linear(src
->format
);
73 src_templ
->u
.tex
.first_level
= srclevel
;
74 src_templ
->u
.tex
.last_level
= srclevel
;
75 src_templ
->u
.tex
.first_layer
= 0;
76 src_templ
->u
.tex
.last_layer
=
77 src
->target
== PIPE_TEXTURE_3D
? u_minify(src
->depth0
, srclevel
) - 1
78 : (unsigned)(src
->array_size
- 1);
79 src_templ
->swizzle_r
= PIPE_SWIZZLE_X
;
80 src_templ
->swizzle_g
= PIPE_SWIZZLE_Y
;
81 src_templ
->swizzle_b
= PIPE_SWIZZLE_Z
;
82 src_templ
->swizzle_a
= PIPE_SWIZZLE_W
;
86 fd_blitter_blit(struct fd_context
*ctx
, const struct pipe_blit_info
*info
)
88 struct pipe_resource
*dst
= info
->dst
.resource
;
89 struct pipe_resource
*src
= info
->src
.resource
;
90 struct pipe_context
*pipe
= &ctx
->base
;
91 struct pipe_surface
*dst_view
, dst_templ
;
92 struct pipe_sampler_view src_templ
, *src_view
;
95 if (!info
->scissor_enable
&& !info
->alpha_blend
) {
96 discard
= util_texrange_covers_whole_level(info
->dst
.resource
,
97 info
->dst
.level
, info
->dst
.box
.x
, info
->dst
.box
.y
,
98 info
->dst
.box
.z
, info
->dst
.box
.width
,
99 info
->dst
.box
.height
, info
->dst
.box
.depth
);
102 fd_blitter_pipe_begin(ctx
, info
->render_condition_enable
, discard
, FD_STAGE_BLIT
);
104 /* Initialize the surface. */
105 default_dst_texture(&dst_templ
, dst
, info
->dst
.level
,
107 dst_templ
.format
= info
->dst
.format
;
108 dst_view
= pipe
->create_surface(pipe
, dst
, &dst_templ
);
110 /* Initialize the sampler view. */
111 default_src_texture(&src_templ
, src
, info
->src
.level
);
112 src_templ
.format
= info
->src
.format
;
113 src_view
= pipe
->create_sampler_view(pipe
, src
, &src_templ
);
116 util_blitter_blit_generic(ctx
->blitter
, dst_view
, &info
->dst
.box
,
117 src_view
, &info
->src
.box
, src
->width0
, src
->height0
,
118 info
->mask
, info
->filter
,
119 info
->scissor_enable
? &info
->scissor
: NULL
,
122 pipe_surface_reference(&dst_view
, NULL
);
123 pipe_sampler_view_reference(&src_view
, NULL
);
125 fd_blitter_pipe_end(ctx
);
127 /* The fallback blitter must never fail: */
132 * _copy_region using pipe (3d engine)
135 fd_blitter_pipe_copy_region(struct fd_context
*ctx
,
136 struct pipe_resource
*dst
,
138 unsigned dstx
, unsigned dsty
, unsigned dstz
,
139 struct pipe_resource
*src
,
141 const struct pipe_box
*src_box
)
143 /* not until we allow rendertargets to be buffers */
144 if (dst
->target
== PIPE_BUFFER
|| src
->target
== PIPE_BUFFER
)
147 if (!util_blitter_is_copy_supported(ctx
->blitter
, dst
, src
))
150 /* TODO we could discard if dst box covers dst level fully.. */
151 fd_blitter_pipe_begin(ctx
, false, false, FD_STAGE_BLIT
);
152 util_blitter_copy_texture(ctx
->blitter
,
153 dst
, dst_level
, dstx
, dsty
, dstz
,
154 src
, src_level
, src_box
);
155 fd_blitter_pipe_end(ctx
);
161 * Copy a block of pixels from one resource to another.
162 * The resource must be of the same format.
165 fd_resource_copy_region(struct pipe_context
*pctx
,
166 struct pipe_resource
*dst
,
168 unsigned dstx
, unsigned dsty
, unsigned dstz
,
169 struct pipe_resource
*src
,
171 const struct pipe_box
*src_box
)
173 struct fd_context
*ctx
= fd_context(pctx
);
176 struct pipe_blit_info info
;
178 memset(&info
, 0, sizeof info
);
179 info
.dst
.resource
= dst
;
180 info
.dst
.level
= dst_level
;
181 info
.dst
.box
.x
= dstx
;
182 info
.dst
.box
.y
= dsty
;
183 info
.dst
.box
.z
= dstz
;
184 info
.dst
.box
.width
= src_box
->width
;
185 info
.dst
.box
.height
= src_box
->height
;
186 assert(info
.dst
.box
.width
>= 0);
187 assert(info
.dst
.box
.height
>= 0);
188 info
.dst
.box
.depth
= 1;
189 info
.dst
.format
= dst
->format
;
190 info
.src
.resource
= src
;
191 info
.src
.level
= src_level
;
192 info
.src
.box
= *src_box
;
193 info
.src
.format
= src
->format
;
194 info
.mask
= util_format_get_mask(src
->format
);
195 info
.filter
= PIPE_TEX_FILTER_NEAREST
;
196 info
.scissor_enable
= 0;
198 if (ctx
->blit(ctx
, &info
))
202 /* TODO if we have 2d core, or other DMA engine that could be used
203 * for simple copies and reasonably easily synchronized with the 3d
204 * core, this is where we'd plug it in..
207 /* try blit on 3d pipe: */
208 if (fd_blitter_pipe_copy_region(ctx
,
209 dst
, dst_level
, dstx
, dsty
, dstz
,
210 src
, src_level
, src_box
))
213 /* else fallback to pure sw: */
214 util_resource_copy_region(pctx
,
215 dst
, dst_level
, dstx
, dsty
, dstz
,
216 src
, src_level
, src_box
);