ac2738f59a0e25b946a3a84d35d70a5bc7fc034e
[mesa.git] / src / mesa / drivers / dri / i965 / intel_copy_image.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2014 Intel Corporation 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 "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Jason Ekstrand <jason.ekstrand@intel.com>
26 */
27
28 #include "intel_tex.h"
29 #include "intel_blit.h"
30 #include "intel_mipmap_tree.h"
31 #include "main/formats.h"
32 #include "drivers/common/meta.h"
33
34 static bool
35 copy_image_with_blitter(struct brw_context *brw,
36 struct intel_mipmap_tree *src_mt, int src_level,
37 int src_x, int src_y, int src_z,
38 struct intel_mipmap_tree *dst_mt, int dst_level,
39 int dst_x, int dst_y, int dst_z,
40 int src_width, int src_height)
41 {
42 GLuint bw, bh;
43 uint32_t src_image_x, src_image_y, dst_image_x, dst_image_y;
44
45 /* The blitter doesn't understand multisampling at all. */
46 if (src_mt->num_samples > 0 || dst_mt->num_samples > 0)
47 return false;
48
49 /* According to the Ivy Bridge PRM, Vol1 Part4, section 1.2.1.2 (Graphics
50 * Data Size Limitations):
51 *
52 * The BLT engine is capable of transferring very large quantities of
53 * graphics data. Any graphics data read from and written to the
54 * destination is permitted to represent a number of pixels that
55 * occupies up to 65,536 scan lines and up to 32,768 bytes per scan line
56 * at the destination. The maximum number of pixels that may be
57 * represented per scan line’s worth of graphics data depends on the
58 * color depth.
59 *
60 * Furthermore, intelEmitCopyBlit (which is called below) uses a signed
61 * 16-bit integer to represent buffer pitch, so it can only handle buffer
62 * pitches < 32k.
63 *
64 * As a result of these two limitations, we can only use the blitter to do
65 * this copy when the miptree's pitch is less than 32k.
66 */
67 if (src_mt->pitch >= 32768 ||
68 dst_mt->pitch >= 32768) {
69 perf_debug("Falling back due to >=32k pitch\n");
70 return false;
71 }
72
73 intel_miptree_get_image_offset(src_mt, src_level, src_z,
74 &src_image_x, &src_image_y);
75
76 if (_mesa_is_format_compressed(src_mt->format)) {
77 _mesa_get_format_block_size(src_mt->format, &bw, &bh);
78
79 assert(src_x % bw == 0);
80 assert(src_y % bh == 0);
81 assert(src_width % bw == 0);
82 assert(src_height % bh == 0);
83
84 src_x /= (int)bw;
85 src_y /= (int)bh;
86 src_width /= (int)bw;
87 src_height /= (int)bh;
88 }
89 src_x += src_image_x;
90 src_y += src_image_y;
91
92 intel_miptree_get_image_offset(dst_mt, dst_level, dst_z,
93 &dst_image_x, &dst_image_y);
94
95 if (_mesa_is_format_compressed(dst_mt->format)) {
96 _mesa_get_format_block_size(dst_mt->format, &bw, &bh);
97
98 assert(dst_x % bw == 0);
99 assert(dst_y % bh == 0);
100
101 dst_x /= (int)bw;
102 dst_y /= (int)bh;
103 }
104 dst_x += dst_image_x;
105 dst_y += dst_image_y;
106
107 return intelEmitCopyBlit(brw,
108 src_mt->cpp,
109 src_mt->pitch,
110 src_mt->bo, src_mt->offset,
111 src_mt->tiling,
112 src_mt->tr_mode,
113 dst_mt->pitch,
114 dst_mt->bo, dst_mt->offset,
115 dst_mt->tiling,
116 dst_mt->tr_mode,
117 src_x, src_y,
118 dst_x, dst_y,
119 src_width, src_height,
120 GL_COPY);
121 }
122
123 static void
124 copy_image_with_memcpy(struct brw_context *brw,
125 struct intel_mipmap_tree *src_mt, int src_level,
126 int src_x, int src_y, int src_z,
127 struct intel_mipmap_tree *dst_mt, int dst_level,
128 int dst_x, int dst_y, int dst_z,
129 int src_width, int src_height)
130 {
131 bool same_slice;
132 void *mapped, *src_mapped, *dst_mapped;
133 ptrdiff_t src_stride, dst_stride, cpp;
134 int map_x1, map_y1, map_x2, map_y2;
135 GLuint src_bw, src_bh;
136
137 cpp = _mesa_get_format_bytes(src_mt->format);
138 _mesa_get_format_block_size(src_mt->format, &src_bw, &src_bh);
139
140 assert(src_width % src_bw == 0);
141 assert(src_height % src_bw == 0);
142 assert(src_x % src_bw == 0);
143 assert(src_y % src_bw == 0);
144
145 /* If we are on the same miptree, same level, and same slice, then
146 * intel_miptree_map won't let us map it twice. We have to do things a
147 * bit differently. In particular, we do a single map large enough for
148 * both portions and in read-write mode.
149 */
150 same_slice = src_mt == dst_mt && src_level == dst_level && src_z == dst_z;
151
152 if (same_slice) {
153 assert(dst_x % src_bw == 0);
154 assert(dst_y % src_bw == 0);
155
156 map_x1 = MIN2(src_x, dst_x);
157 map_y1 = MIN2(src_y, dst_y);
158 map_x2 = MAX2(src_x, dst_x) + src_width;
159 map_y2 = MAX2(src_y, dst_y) + src_height;
160
161 intel_miptree_map(brw, src_mt, src_level, src_z,
162 map_x1, map_y1, map_x2 - map_x1, map_y2 - map_y1,
163 GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
164 &mapped, &src_stride);
165
166 dst_stride = src_stride;
167
168 /* Set the offsets here so we don't have to think about while looping */
169 src_mapped = mapped + ((src_y - map_y1) / src_bh) * src_stride +
170 ((src_x - map_x1) / src_bw) * cpp;
171 dst_mapped = mapped + ((dst_y - map_y1) / src_bh) * dst_stride +
172 ((dst_x - map_x1) / src_bw) * cpp;
173 } else {
174 intel_miptree_map(brw, src_mt, src_level, src_z,
175 src_x, src_y, src_width, src_height,
176 GL_MAP_READ_BIT, &src_mapped, &src_stride);
177 intel_miptree_map(brw, dst_mt, dst_level, dst_z,
178 dst_x, dst_y, src_width, src_height,
179 GL_MAP_WRITE_BIT, &dst_mapped, &dst_stride);
180 }
181
182 src_width /= (int)src_bw;
183 src_height /= (int)src_bh;
184
185 for (int i = 0; i < src_height; ++i) {
186 memcpy(dst_mapped, src_mapped, src_width * cpp);
187 src_mapped += src_stride;
188 dst_mapped += dst_stride;
189 }
190
191 if (same_slice) {
192 intel_miptree_unmap(brw, src_mt, src_level, src_z);
193 } else {
194 intel_miptree_unmap(brw, dst_mt, dst_level, dst_z);
195 intel_miptree_unmap(brw, src_mt, src_level, src_z);
196 }
197 }
198
199 static void
200 intel_copy_image_sub_data(struct gl_context *ctx,
201 struct gl_texture_image *src_image,
202 int src_x, int src_y, int src_z,
203 struct gl_texture_image *dst_image,
204 int dst_x, int dst_y, int dst_z,
205 int src_width, int src_height)
206 {
207 struct brw_context *brw = brw_context(ctx);
208 struct intel_texture_image *intel_src_image = intel_texture_image(src_image);
209 struct intel_texture_image *intel_dst_image = intel_texture_image(dst_image);
210
211 if (_mesa_meta_CopyImageSubData_uncompressed(ctx,
212 src_image, src_x, src_y, src_z,
213 dst_image, dst_x, dst_y, dst_z,
214 src_width, src_height)) {
215 return;
216 }
217
218 if (intel_src_image->mt->num_samples > 0 ||
219 intel_dst_image->mt->num_samples > 0) {
220 _mesa_problem(ctx, "Failed to copy multisampled texture with meta path\n");
221 return;
222 }
223
224 /* Cube maps actually have different images per face */
225 if (src_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
226 src_z = src_image->Face;
227 if (dst_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
228 dst_z = dst_image->Face;
229
230 /* We are now going to try and copy the texture using the blitter. If
231 * that fails, we will fall back mapping the texture and using memcpy.
232 * In either case, we need to do a full resolve.
233 */
234 intel_miptree_all_slices_resolve_hiz(brw, intel_src_image->mt);
235 intel_miptree_all_slices_resolve_depth(brw, intel_src_image->mt);
236 intel_miptree_resolve_color(brw, intel_src_image->mt);
237
238 intel_miptree_all_slices_resolve_hiz(brw, intel_dst_image->mt);
239 intel_miptree_all_slices_resolve_depth(brw, intel_dst_image->mt);
240 intel_miptree_resolve_color(brw, intel_dst_image->mt);
241
242 unsigned src_level = src_image->Level + src_image->TexObject->MinLevel;
243 unsigned dst_level = dst_image->Level + dst_image->TexObject->MinLevel;
244 if (copy_image_with_blitter(brw, intel_src_image->mt, src_level,
245 src_x, src_y, src_z,
246 intel_dst_image->mt, dst_level,
247 dst_x, dst_y, dst_z,
248 src_width, src_height))
249 return;
250
251 /* This is a worst-case scenario software fallback that maps the two
252 * textures and does a memcpy between them.
253 */
254 copy_image_with_memcpy(brw, intel_src_image->mt, src_level,
255 src_x, src_y, src_z,
256 intel_dst_image->mt, dst_level,
257 dst_x, dst_y, dst_z,
258 src_width, src_height);
259 }
260
261 void
262 intelInitCopyImageFuncs(struct dd_function_table *functions)
263 {
264 functions->CopyImageSubData = intel_copy_image_sub_data;
265 }