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