glsl: lower mediump temporaries to 16 bits except structures (v2)
[mesa.git] / src / mesa / state_tracker / st_cb_copyimage.c
1 /*
2 * Copyright 2015 Advanced Micro Devices, Inc.
3 *
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
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
13 * Software.
14 *
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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25 #include "state_tracker/st_context.h"
26 #include "state_tracker/st_cb_bitmap.h"
27 #include "state_tracker/st_cb_copyimage.h"
28 #include "state_tracker/st_cb_fbo.h"
29 #include "state_tracker/st_texture.h"
30 #include "state_tracker/st_util.h"
31
32 #include "util/u_box.h"
33 #include "util/format/u_format.h"
34 #include "util/u_inlines.h"
35
36
37 /**
38 * Return an equivalent canonical format without "X" channels.
39 *
40 * Copying between incompatible formats is easier when the format is
41 * canonicalized, meaning that it is in a standard form.
42 *
43 * The returned format has the same component sizes and swizzles as
44 * the source format, the type is changed to UINT or UNORM, depending on
45 * which one has the most swizzle combinations in their group.
46 *
47 * If it's not an array format, return a memcpy-equivalent array format.
48 *
49 * The key feature is that swizzled versions of formats of the same
50 * component size always return the same component type.
51 *
52 * X returns A.
53 * Luminance, intensity, alpha, depth, stencil, and 8-bit and 16-bit packed
54 * formats are not supported. (same as ARB_copy_image)
55 */
56 static enum pipe_format
57 get_canonical_format(enum pipe_format format)
58 {
59 const struct util_format_description *desc =
60 util_format_description(format);
61
62 /* Packed formats. Return the equivalent array format. */
63 if (format == PIPE_FORMAT_R11G11B10_FLOAT ||
64 format == PIPE_FORMAT_R9G9B9E5_FLOAT)
65 return get_canonical_format(PIPE_FORMAT_R8G8B8A8_UINT);
66
67 if (desc->nr_channels == 4 &&
68 desc->channel[0].size == 10 &&
69 desc->channel[1].size == 10 &&
70 desc->channel[2].size == 10 &&
71 desc->channel[3].size == 2) {
72 if (desc->swizzle[0] == PIPE_SWIZZLE_X &&
73 desc->swizzle[1] == PIPE_SWIZZLE_Y &&
74 desc->swizzle[2] == PIPE_SWIZZLE_Z)
75 return get_canonical_format(PIPE_FORMAT_R8G8B8A8_UINT);
76
77 return PIPE_FORMAT_NONE;
78 }
79
80 #define RETURN_FOR_SWIZZLE1(x, format) \
81 if (desc->swizzle[0] == PIPE_SWIZZLE_##x) \
82 return format
83
84 #define RETURN_FOR_SWIZZLE2(x, y, format) \
85 if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
86 desc->swizzle[1] == PIPE_SWIZZLE_##y) \
87 return format
88
89 #define RETURN_FOR_SWIZZLE3(x, y, z, format) \
90 if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
91 desc->swizzle[1] == PIPE_SWIZZLE_##y && \
92 desc->swizzle[2] == PIPE_SWIZZLE_##z) \
93 return format
94
95 #define RETURN_FOR_SWIZZLE4(x, y, z, w, format) \
96 if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
97 desc->swizzle[1] == PIPE_SWIZZLE_##y && \
98 desc->swizzle[2] == PIPE_SWIZZLE_##z && \
99 desc->swizzle[3] == PIPE_SWIZZLE_##w) \
100 return format
101
102 /* Array formats. */
103 if (desc->is_array) {
104 switch (desc->nr_channels) {
105 case 1:
106 switch (desc->channel[0].size) {
107 case 8:
108 RETURN_FOR_SWIZZLE1(X, PIPE_FORMAT_R8_UINT);
109 break;
110
111 case 16:
112 RETURN_FOR_SWIZZLE1(X, PIPE_FORMAT_R16_UINT);
113 break;
114
115 case 32:
116 RETURN_FOR_SWIZZLE1(X, PIPE_FORMAT_R32_UINT);
117 break;
118 }
119 break;
120
121 case 2:
122 switch (desc->channel[0].size) {
123 case 8:
124 /* All formats in each group must be of the same type.
125 * We can't use UINT for R8G8 while using UNORM for G8R8.
126 */
127 RETURN_FOR_SWIZZLE2(X, Y, PIPE_FORMAT_R8G8_UNORM);
128 RETURN_FOR_SWIZZLE2(Y, X, PIPE_FORMAT_G8R8_UNORM);
129 break;
130
131 case 16:
132 RETURN_FOR_SWIZZLE2(X, Y, PIPE_FORMAT_R16G16_UNORM);
133 RETURN_FOR_SWIZZLE2(Y, X, PIPE_FORMAT_G16R16_UNORM);
134 break;
135
136 case 32:
137 RETURN_FOR_SWIZZLE2(X, Y, PIPE_FORMAT_R32G32_UINT);
138 break;
139 }
140 break;
141
142 case 3:
143 switch (desc->channel[0].size) {
144 case 8:
145 RETURN_FOR_SWIZZLE3(X, Y, Z, PIPE_FORMAT_R8G8B8_UINT);
146 break;
147
148 case 16:
149 RETURN_FOR_SWIZZLE3(X, Y, Z, PIPE_FORMAT_R16G16B16_UINT);
150 break;
151
152 case 32:
153 RETURN_FOR_SWIZZLE3(X, Y, Z, PIPE_FORMAT_R32G32B32_UINT);
154 break;
155 }
156 break;
157
158 case 4:
159 switch (desc->channel[0].size) {
160 case 8:
161 RETURN_FOR_SWIZZLE4(X, Y, Z, W, PIPE_FORMAT_R8G8B8A8_UNORM);
162 RETURN_FOR_SWIZZLE4(X, Y, Z, 1, PIPE_FORMAT_R8G8B8A8_UNORM);
163 RETURN_FOR_SWIZZLE4(Z, Y, X, W, PIPE_FORMAT_B8G8R8A8_UNORM);
164 RETURN_FOR_SWIZZLE4(Z, Y, X, 1, PIPE_FORMAT_B8G8R8A8_UNORM);
165 RETURN_FOR_SWIZZLE4(W, Z, Y, X, PIPE_FORMAT_A8B8G8R8_UNORM);
166 RETURN_FOR_SWIZZLE4(W, Z, Y, 1, PIPE_FORMAT_A8B8G8R8_UNORM);
167 RETURN_FOR_SWIZZLE4(Y, Z, W, X, PIPE_FORMAT_A8R8G8B8_UNORM);
168 RETURN_FOR_SWIZZLE4(Y, Z, W, 1, PIPE_FORMAT_A8R8G8B8_UNORM);
169 break;
170
171 case 16:
172 RETURN_FOR_SWIZZLE4(X, Y, Z, W, PIPE_FORMAT_R16G16B16A16_UINT);
173 RETURN_FOR_SWIZZLE4(X, Y, Z, 1, PIPE_FORMAT_R16G16B16A16_UINT);
174 break;
175
176 case 32:
177 RETURN_FOR_SWIZZLE4(X, Y, Z, W, PIPE_FORMAT_R32G32B32A32_UINT);
178 RETURN_FOR_SWIZZLE4(X, Y, Z, 1, PIPE_FORMAT_R32G32B32A32_UINT);
179 break;
180 }
181 }
182
183 assert(!"unknown array format");
184 return PIPE_FORMAT_NONE;
185 }
186
187 assert(!"unknown packed format");
188 return PIPE_FORMAT_NONE;
189 }
190
191 /**
192 * Return true if the swizzle is XYZW in case of a 4-channel format,
193 * XY in case of a 2-channel format, or X in case of a 1-channel format.
194 */
195 static bool
196 has_identity_swizzle(const struct util_format_description *desc)
197 {
198 int i;
199
200 for (i = 0; i < desc->nr_channels; i++)
201 if (desc->swizzle[i] != PIPE_SWIZZLE_X + i)
202 return false;
203
204 return true;
205 }
206
207 /**
208 * Return a canonical format for the given bits and channel size.
209 */
210 static enum pipe_format
211 canonical_format_from_bits(unsigned bits, unsigned channel_size)
212 {
213 switch (bits) {
214 case 8:
215 if (channel_size == 8)
216 return get_canonical_format(PIPE_FORMAT_R8_UINT);
217 break;
218
219 case 16:
220 if (channel_size == 8)
221 return get_canonical_format(PIPE_FORMAT_R8G8_UINT);
222 if (channel_size == 16)
223 return get_canonical_format(PIPE_FORMAT_R16_UINT);
224 break;
225
226 case 32:
227 if (channel_size == 8)
228 return get_canonical_format(PIPE_FORMAT_R8G8B8A8_UINT);
229 if (channel_size == 16)
230 return get_canonical_format(PIPE_FORMAT_R16G16_UINT);
231 if (channel_size == 32)
232 return get_canonical_format(PIPE_FORMAT_R32_UINT);
233 break;
234
235 case 64:
236 if (channel_size == 16)
237 return get_canonical_format(PIPE_FORMAT_R16G16B16A16_UINT);
238 if (channel_size == 32)
239 return get_canonical_format(PIPE_FORMAT_R32G32_UINT);
240 break;
241
242 case 128:
243 if (channel_size == 32)
244 return get_canonical_format(PIPE_FORMAT_R32G32B32A32_UINT);
245 break;
246 }
247
248 assert(!"impossible format");
249 return PIPE_FORMAT_NONE;
250 }
251
252 static void
253 blit(struct pipe_context *pipe,
254 struct pipe_resource *dst,
255 enum pipe_format dst_format,
256 unsigned dst_level,
257 unsigned dstx, unsigned dsty, unsigned dstz,
258 struct pipe_resource *src,
259 enum pipe_format src_format,
260 unsigned src_level,
261 const struct pipe_box *src_box)
262 {
263 struct pipe_blit_info blit = {{0}};
264
265 blit.src.resource = src;
266 blit.dst.resource = dst;
267 blit.src.format = src_format;
268 blit.dst.format = dst_format;
269 blit.src.level = src_level;
270 blit.dst.level = dst_level;
271 blit.src.box = *src_box;
272 u_box_3d(dstx, dsty, dstz, src_box->width, src_box->height,
273 src_box->depth, &blit.dst.box);
274 blit.mask = PIPE_MASK_RGBA;
275 blit.filter = PIPE_TEX_FILTER_NEAREST;
276
277 pipe->blit(pipe, &blit);
278 }
279
280 static void
281 swizzled_copy(struct pipe_context *pipe,
282 struct pipe_resource *dst,
283 unsigned dst_level,
284 unsigned dstx, unsigned dsty, unsigned dstz,
285 struct pipe_resource *src,
286 unsigned src_level,
287 const struct pipe_box *src_box)
288 {
289 const struct util_format_description *src_desc, *dst_desc;
290 unsigned bits;
291 enum pipe_format blit_src_format, blit_dst_format;
292
293 /* Get equivalent canonical formats. Those are always array formats and
294 * copying between compatible canonical formats behaves either like
295 * memcpy or like swizzled memcpy. The idea is that we won't have to care
296 * about the channel type from this point on.
297 * Only the swizzle and channel size.
298 */
299 blit_src_format = get_canonical_format(src->format);
300 blit_dst_format = get_canonical_format(dst->format);
301
302 assert(blit_src_format != PIPE_FORMAT_NONE);
303 assert(blit_dst_format != PIPE_FORMAT_NONE);
304
305 src_desc = util_format_description(blit_src_format);
306 dst_desc = util_format_description(blit_dst_format);
307
308 assert(src_desc->block.bits == dst_desc->block.bits);
309 bits = src_desc->block.bits;
310
311 if (dst_desc->channel[0].size == src_desc->channel[0].size) {
312 /* Only the swizzle is different, which means we can just blit,
313 * e.g. RGBA -> BGRA.
314 */
315 } else if (has_identity_swizzle(src_desc)) {
316 /* Src is unswizzled and dst can be swizzled, so src is typecast
317 * to an equivalent dst-compatible format.
318 * e.g. R32 -> BGRA8 is realized as RGBA8 -> BGRA8
319 */
320 blit_src_format =
321 canonical_format_from_bits(bits, dst_desc->channel[0].size);
322 } else if (has_identity_swizzle(dst_desc)) {
323 /* Dst is unswizzled and src can be swizzled, so dst is typecast
324 * to an equivalent src-compatible format.
325 * e.g. BGRA8 -> R32 is realized as BGRA8 -> RGBA8
326 */
327 blit_dst_format =
328 canonical_format_from_bits(bits, src_desc->channel[0].size);
329 } else {
330 assert(!"This should have been handled by handle_complex_copy.");
331 return;
332 }
333
334 blit(pipe, dst, blit_dst_format, dst_level, dstx, dsty, dstz,
335 src, blit_src_format, src_level, src_box);
336 }
337
338 static bool
339 same_size_and_swizzle(const struct util_format_description *d1,
340 const struct util_format_description *d2)
341 {
342 int i;
343
344 if (d1->layout != d2->layout ||
345 d1->nr_channels != d2->nr_channels ||
346 d1->is_array != d2->is_array)
347 return false;
348
349 for (i = 0; i < d1->nr_channels; i++) {
350 if (d1->channel[i].size != d2->channel[i].size)
351 return false;
352
353 if (d1->swizzle[i] <= PIPE_SWIZZLE_W &&
354 d2->swizzle[i] <= PIPE_SWIZZLE_W &&
355 d1->swizzle[i] != d2->swizzle[i])
356 return false;
357 }
358
359 return true;
360 }
361
362 static struct pipe_resource *
363 create_texture(struct pipe_screen *screen, enum pipe_format format,
364 unsigned nr_samples, unsigned nr_storage_samples,
365 unsigned width, unsigned height, unsigned depth)
366 {
367 struct pipe_resource templ;
368
369 memset(&templ, 0, sizeof(templ));
370 templ.format = format;
371 templ.width0 = width;
372 templ.height0 = height;
373 templ.depth0 = 1;
374 templ.array_size = depth;
375 templ.nr_samples = nr_samples;
376 templ.nr_storage_samples = nr_storage_samples;
377 templ.usage = PIPE_USAGE_DEFAULT;
378 templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
379
380 if (depth > 1)
381 templ.target = PIPE_TEXTURE_2D_ARRAY;
382 else
383 templ.target = PIPE_TEXTURE_2D;
384
385 return screen->resource_create(screen, &templ);
386 }
387
388 /**
389 * Handle complex format conversions using 2 blits with a temporary texture
390 * in between, e.g. blitting from B10G10R10A2 to G16R16.
391 *
392 * This example is implemented this way:
393 * 1) First, blit from B10G10R10A2 to R10G10B10A2, which is canonical, so it
394 * can be reinterpreted as a different canonical format of the same bpp,
395 * such as R16G16. This blit only swaps R and B 10-bit components.
396 * 2) Finally, blit the result, which is R10G10B10A2, as R16G16 to G16R16.
397 * This blit only swaps R and G 16-bit components.
398 */
399 static bool
400 handle_complex_copy(struct pipe_context *pipe,
401 struct pipe_resource *dst,
402 unsigned dst_level,
403 unsigned dstx, unsigned dsty, unsigned dstz,
404 struct pipe_resource *src,
405 unsigned src_level,
406 const struct pipe_box *src_box,
407 enum pipe_format noncanon_format,
408 enum pipe_format canon_format)
409 {
410 struct pipe_box temp_box;
411 struct pipe_resource *temp = NULL;
412 const struct util_format_description *src_desc, *dst_desc;
413 const struct util_format_description *canon_desc, *noncanon_desc;
414 bool src_is_canon;
415 bool src_is_noncanon;
416 bool dst_is_canon;
417 bool dst_is_noncanon;
418
419 src_desc = util_format_description(src->format);
420 dst_desc = util_format_description(dst->format);
421 canon_desc = util_format_description(canon_format);
422 noncanon_desc = util_format_description(noncanon_format);
423
424 src_is_canon = same_size_and_swizzle(src_desc, canon_desc);
425 dst_is_canon = same_size_and_swizzle(dst_desc, canon_desc);
426 src_is_noncanon = same_size_and_swizzle(src_desc, noncanon_desc);
427 dst_is_noncanon = same_size_and_swizzle(dst_desc, noncanon_desc);
428
429 if (src_is_noncanon) {
430 /* Simple case - only types differ (e.g. UNORM and UINT). */
431 if (dst_is_noncanon) {
432 blit(pipe, dst, noncanon_format, dst_level, dstx, dsty, dstz, src,
433 noncanon_format, src_level, src_box);
434 return true;
435 }
436
437 /* Simple case - only types and swizzles differ. */
438 if (dst_is_canon) {
439 blit(pipe, dst, canon_format, dst_level, dstx, dsty, dstz, src,
440 noncanon_format, src_level, src_box);
441 return true;
442 }
443
444 /* Use the temporary texture. Src is converted to a canonical format,
445 * then proceed the generic swizzled_copy.
446 */
447 temp = create_texture(pipe->screen, canon_format, src->nr_samples,
448 src->nr_storage_samples, src_box->width,
449 src_box->height, src_box->depth);
450
451 u_box_3d(0, 0, 0, src_box->width, src_box->height, src_box->depth,
452 &temp_box);
453
454 blit(pipe, temp, canon_format, 0, 0, 0, 0, src, noncanon_format,
455 src_level, src_box);
456 swizzled_copy(pipe, dst, dst_level, dstx, dsty, dstz, temp, 0,
457 &temp_box);
458 pipe_resource_reference(&temp, NULL);
459 return true;
460 }
461
462 if (dst_is_noncanon) {
463 /* Simple case - only types and swizzles differ. */
464 if (src_is_canon) {
465 blit(pipe, dst, noncanon_format, dst_level, dstx, dsty, dstz, src,
466 canon_format, src_level, src_box);
467 return true;
468 }
469
470 /* Use the temporary texture. First, use the generic copy, but use
471 * a canonical format in the destination. Then convert */
472 temp = create_texture(pipe->screen, canon_format, dst->nr_samples,
473 dst->nr_storage_samples, src_box->width,
474 src_box->height, src_box->depth);
475
476 u_box_3d(0, 0, 0, src_box->width, src_box->height, src_box->depth,
477 &temp_box);
478
479 swizzled_copy(pipe, temp, 0, 0, 0, 0, src, src_level, src_box);
480 blit(pipe, dst, noncanon_format, dst_level, dstx, dsty, dstz, temp,
481 canon_format, 0, &temp_box);
482 pipe_resource_reference(&temp, NULL);
483 return true;
484 }
485
486 return false;
487 }
488
489 static void
490 copy_image(struct pipe_context *pipe,
491 struct pipe_resource *dst,
492 unsigned dst_level,
493 unsigned dstx, unsigned dsty, unsigned dstz,
494 struct pipe_resource *src,
495 unsigned src_level,
496 const struct pipe_box *src_box)
497 {
498 if (src->format == dst->format ||
499 util_format_is_compressed(src->format) ||
500 util_format_is_compressed(dst->format)) {
501 pipe->resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
502 src, src_level, src_box);
503 return;
504 }
505
506 /* Copying to/from B10G10R10*2 needs 2 blits with R10G10B10A2
507 * as a temporary texture in between.
508 */
509 if (handle_complex_copy(pipe, dst, dst_level, dstx, dsty, dstz, src,
510 src_level, src_box, PIPE_FORMAT_B10G10R10A2_UINT,
511 PIPE_FORMAT_R10G10B10A2_UINT))
512 return;
513
514 /* Copying to/from G8R8 needs 2 blits with R8G8 as a temporary texture
515 * in between.
516 */
517 if (handle_complex_copy(pipe, dst, dst_level, dstx, dsty, dstz, src,
518 src_level, src_box, PIPE_FORMAT_G8R8_UNORM,
519 PIPE_FORMAT_R8G8_UNORM))
520 return;
521
522 /* Copying to/from G16R16 needs 2 blits with R16G16 as a temporary texture
523 * in between.
524 */
525 if (handle_complex_copy(pipe, dst, dst_level, dstx, dsty, dstz, src,
526 src_level, src_box, PIPE_FORMAT_G16R16_UNORM,
527 PIPE_FORMAT_R16G16_UNORM))
528 return;
529
530 /* Only allow non-identity swizzling on RGBA8 formats. */
531
532 /* Simple copy, memcpy with swizzling, no format conversion. */
533 swizzled_copy(pipe, dst, dst_level, dstx, dsty, dstz, src, src_level,
534 src_box);
535 }
536
537 static void
538 fallback_copy_image(struct st_context *st,
539 struct gl_texture_image *dst_image,
540 struct pipe_resource *dst_res,
541 int dst_x, int dst_y, int dst_z,
542 struct gl_texture_image *src_image,
543 struct pipe_resource *src_res,
544 int src_x, int src_y, int src_z,
545 int src_w, int src_h)
546 {
547 uint8_t *dst, *src;
548 int dst_stride, src_stride;
549 struct pipe_transfer *dst_transfer, *src_transfer;
550 unsigned line_bytes;
551
552 bool dst_is_compressed = dst_image && _mesa_is_format_compressed(dst_image->TexFormat);
553 bool src_is_compressed = src_image && _mesa_is_format_compressed(src_image->TexFormat);
554
555 unsigned dst_blk_w = 1, dst_blk_h = 1, src_blk_w = 1, src_blk_h = 1;
556 if (dst_image)
557 _mesa_get_format_block_size(dst_image->TexFormat, &dst_blk_w, &dst_blk_h);
558 if (src_image)
559 _mesa_get_format_block_size(src_image->TexFormat, &src_blk_w, &src_blk_h);
560
561 unsigned dst_w = src_w;
562 unsigned dst_h = src_h;
563 unsigned lines = src_h;
564
565 if (src_is_compressed && !dst_is_compressed) {
566 dst_w = DIV_ROUND_UP(dst_w, src_blk_w);
567 dst_h = DIV_ROUND_UP(dst_h, src_blk_h);
568 } else if (!src_is_compressed && dst_is_compressed) {
569 dst_w *= dst_blk_w;
570 dst_h *= dst_blk_h;
571 }
572 if (src_is_compressed) {
573 lines = DIV_ROUND_UP(lines, src_blk_h);
574 }
575
576 if (src_image)
577 line_bytes = _mesa_format_row_stride(src_image->TexFormat, src_w);
578 else
579 line_bytes = _mesa_format_row_stride(dst_image->TexFormat, dst_w);
580
581 if (dst_image) {
582 st->ctx->Driver.MapTextureImage(
583 st->ctx, dst_image, dst_z,
584 dst_x, dst_y, dst_w, dst_h,
585 GL_MAP_WRITE_BIT, &dst, &dst_stride);
586 } else {
587 dst = pipe_transfer_map(st->pipe, dst_res, 0, dst_z,
588 PIPE_TRANSFER_WRITE,
589 dst_x, dst_y, dst_w, dst_h,
590 &dst_transfer);
591 dst_stride = dst_transfer->stride;
592 }
593
594 if (src_image) {
595 st->ctx->Driver.MapTextureImage(
596 st->ctx, src_image, src_z,
597 src_x, src_y, src_w, src_h,
598 GL_MAP_READ_BIT, &src, &src_stride);
599 } else {
600 src = pipe_transfer_map(st->pipe, src_res, 0, src_z,
601 PIPE_TRANSFER_READ,
602 src_x, src_y, src_w, src_h,
603 &src_transfer);
604 src_stride = src_transfer->stride;
605 }
606
607 for (int y = 0; y < lines; y++) {
608 memcpy(dst, src, line_bytes);
609 dst += dst_stride;
610 src += src_stride;
611 }
612
613 if (dst_image) {
614 st->ctx->Driver.UnmapTextureImage(st->ctx, dst_image, dst_z);
615 } else {
616 pipe_transfer_unmap(st->pipe, dst_transfer);
617 }
618
619 if (src_image) {
620 st->ctx->Driver.UnmapTextureImage(st->ctx, src_image, src_z);
621 } else {
622 pipe_transfer_unmap(st->pipe, src_transfer);
623 }
624 }
625
626 static void
627 st_CopyImageSubData(struct gl_context *ctx,
628 struct gl_texture_image *src_image,
629 struct gl_renderbuffer *src_renderbuffer,
630 int src_x, int src_y, int src_z,
631 struct gl_texture_image *dst_image,
632 struct gl_renderbuffer *dst_renderbuffer,
633 int dst_x, int dst_y, int dst_z,
634 int src_width, int src_height)
635 {
636 struct st_context *st = st_context(ctx);
637 struct pipe_context *pipe = st->pipe;
638 struct pipe_resource *src_res, *dst_res;
639 struct pipe_box box;
640 int src_level, dst_level;
641 int orig_src_z = src_z, orig_dst_z = dst_z;
642
643 st_flush_bitmap_cache(st);
644 st_invalidate_readpix_cache(st);
645
646 if (src_image) {
647 struct st_texture_image *src = st_texture_image(src_image);
648 struct st_texture_object *stObj = st_texture_object(src_image->TexObject);
649 src_res = src->pt;
650 src_level = stObj->pt != src_res ? 0 : src_image->Level;
651 src_z += src_image->Face;
652 if (src_image->TexObject->Immutable) {
653 src_level += src_image->TexObject->MinLevel;
654 src_z += src_image->TexObject->MinLayer;
655 }
656 } else {
657 struct st_renderbuffer *src = st_renderbuffer(src_renderbuffer);
658 src_res = src->texture;
659 src_level = 0;
660 }
661
662 if (dst_image) {
663 struct st_texture_image *dst = st_texture_image(dst_image);
664 struct st_texture_object *stObj = st_texture_object(dst_image->TexObject);
665 dst_res = dst->pt;
666 dst_level = stObj->pt != dst_res ? 0 : dst_image->Level;
667 dst_z += dst_image->Face;
668 if (dst_image->TexObject->Immutable) {
669 dst_level += dst_image->TexObject->MinLevel;
670 dst_z += dst_image->TexObject->MinLayer;
671 }
672 } else {
673 struct st_renderbuffer *dst = st_renderbuffer(dst_renderbuffer);
674 dst_res = dst->texture;
675 dst_level = 0;
676 }
677
678 u_box_2d_zslice(src_x, src_y, src_z, src_width, src_height, &box);
679
680 if ((src_image && st_compressed_format_fallback(st, src_image->TexFormat)) ||
681 (dst_image && st_compressed_format_fallback(st, dst_image->TexFormat))) {
682 fallback_copy_image(st, dst_image, dst_res, dst_x, dst_y, orig_dst_z,
683 src_image, src_res, src_x, src_y, orig_src_z,
684 src_width, src_height);
685 } else {
686 copy_image(pipe, dst_res, dst_level, dst_x, dst_y, dst_z,
687 src_res, src_level, &box);
688 }
689 }
690
691 void
692 st_init_copy_image_functions(struct dd_function_table *functions)
693 {
694 functions->CopyImageSubData = st_CopyImageSubData;
695 }