Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright © 2014 Broadcom
3
 * Copyright (C) 2012 Rob Clark 
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * copy of this software and associated documentation files (the "Software"),
7
 * to deal in the Software without restriction, including without limitation
8
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
 * and/or sell copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice (including the next
13
 * paragraph) shall be included in all copies or substantial portions of the
14
 * Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * 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 OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
 * IN THE SOFTWARE.
23
 */
24
 
25
#include "util/u_memory.h"
26
#include "util/u_format.h"
27
#include "util/u_inlines.h"
28
#include "util/u_surface.h"
29
 
30
#include "vc4_screen.h"
31
#include "vc4_context.h"
32
#include "vc4_resource.h"
33
#include "vc4_tiling.h"
34
 
35
static bool miptree_debug = false;
36
 
37
static void
38
vc4_resource_bo_alloc(struct vc4_resource *rsc)
39
{
40
        struct pipe_resource *prsc = &rsc->base.b;
41
        struct pipe_screen *pscreen = prsc->screen;
42
 
43
        if (miptree_debug) {
44
                fprintf(stderr, "alloc %p: size %d + offset %d -> %d\n",
45
                        rsc,
46
                        rsc->slices[0].size,
47
                        rsc->slices[0].offset,
48
                        rsc->slices[0].offset +
49
                        rsc->slices[0].size +
50
                        rsc->cube_map_stride * (prsc->array_size - 1));
51
        }
52
 
53
        vc4_bo_unreference(&rsc->bo);
54
        rsc->bo = vc4_bo_alloc(vc4_screen(pscreen),
55
                               rsc->slices[0].offset +
56
                               rsc->slices[0].size +
57
                               rsc->cube_map_stride * (prsc->array_size - 1),
58
                               "resource");
59
}
60
 
61
static void
62
vc4_resource_transfer_unmap(struct pipe_context *pctx,
63
                            struct pipe_transfer *ptrans)
64
{
65
        struct vc4_context *vc4 = vc4_context(pctx);
66
        struct vc4_transfer *trans = vc4_transfer(ptrans);
67
        struct pipe_resource *prsc = ptrans->resource;
68
        struct vc4_resource *rsc = vc4_resource(prsc);
69
        struct vc4_resource_slice *slice = &rsc->slices[ptrans->level];
70
 
71
        if (trans->map) {
72
                if (ptrans->usage & PIPE_TRANSFER_WRITE) {
73
                        vc4_store_tiled_image(rsc->bo->map + slice->offset +
74
                                              ptrans->box.z * rsc->cube_map_stride,
75
                                              slice->stride,
76
                                              trans->map, ptrans->stride,
77
                                              slice->tiling, rsc->cpp,
78
                                              &ptrans->box);
79
                }
80
                free(trans->map);
81
        }
82
 
83
        pipe_resource_reference(&ptrans->resource, NULL);
84
        util_slab_free(&vc4->transfer_pool, ptrans);
85
}
86
 
87
static void *
88
vc4_resource_transfer_map(struct pipe_context *pctx,
89
                          struct pipe_resource *prsc,
90
                          unsigned level, unsigned usage,
91
                          const struct pipe_box *box,
92
                          struct pipe_transfer **pptrans)
93
{
94
        struct vc4_context *vc4 = vc4_context(pctx);
95
        struct vc4_resource *rsc = vc4_resource(prsc);
96
        struct vc4_resource_slice *slice = &rsc->slices[level];
97
        struct vc4_transfer *trans;
98
        struct pipe_transfer *ptrans;
99
        enum pipe_format format = prsc->format;
100
        char *buf;
101
 
102
        if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
103
                vc4_resource_bo_alloc(rsc);
104
        } else if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
105
                if (vc4_cl_references_bo(pctx, rsc->bo)) {
106
                        if ((usage & PIPE_TRANSFER_DISCARD_RANGE) &&
107
                            prsc->last_level == 0 &&
108
                            prsc->width0 == box->width &&
109
                            prsc->height0 == box->height &&
110
                            prsc->depth0 == box->depth) {
111
                                vc4_resource_bo_alloc(rsc);
112
                        } else {
113
                                vc4_flush(pctx);
114
                        }
115
                }
116
        }
117
 
118
        if (usage & PIPE_TRANSFER_WRITE)
119
                rsc->writes++;
120
 
121
        trans = util_slab_alloc(&vc4->transfer_pool);
122
        if (!trans)
123
                return NULL;
124
 
125
        /* XXX: Handle DONTBLOCK, DISCARD_RANGE, PERSISTENT, COHERENT. */
126
 
127
        /* util_slab_alloc() doesn't zero: */
128
        memset(trans, 0, sizeof(*trans));
129
        ptrans = &trans->base;
130
 
131
        pipe_resource_reference(&ptrans->resource, prsc);
132
        ptrans->level = level;
133
        ptrans->usage = usage;
134
        ptrans->box = *box;
135
 
136
        /* Note that the current kernel implementation is synchronous, so no
137
         * need to do syncing stuff here yet.
138
         */
139
 
140
        if (usage & PIPE_TRANSFER_UNSYNCHRONIZED)
141
                buf = vc4_bo_map_unsynchronized(rsc->bo);
142
        else
143
                buf = vc4_bo_map(rsc->bo);
144
        if (!buf) {
145
                fprintf(stderr, "Failed to map bo\n");
146
                goto fail;
147
        }
148
 
149
        *pptrans = ptrans;
150
 
151
        if (rsc->tiled) {
152
                uint32_t utile_w = vc4_utile_width(rsc->cpp);
153
                uint32_t utile_h = vc4_utile_height(rsc->cpp);
154
 
155
                /* No direct mappings of tiled, since we need to manually
156
                 * tile/untile.
157
                 */
158
                if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
159
                        return NULL;
160
 
161
                /* We need to align the box to utile boundaries, since that's
162
                 * what load/store operate on.
163
                 */
164
                uint32_t box_start_x = ptrans->box.x & (utile_w - 1);
165
                uint32_t box_start_y = ptrans->box.y & (utile_h - 1);
166
                ptrans->box.width += box_start_x;
167
                ptrans->box.x -= box_start_x;
168
                ptrans->box.height += box_start_y;
169
                ptrans->box.y -= box_start_y;
170
                ptrans->box.width = align(ptrans->box.width, utile_w);
171
                ptrans->box.height = align(ptrans->box.height, utile_h);
172
 
173
                ptrans->stride = ptrans->box.width * rsc->cpp;
174
                ptrans->layer_stride = ptrans->stride;
175
 
176
                trans->map = malloc(ptrans->stride * ptrans->box.height);
177
                if (usage & PIPE_TRANSFER_READ) {
178
                        vc4_load_tiled_image(trans->map, ptrans->stride,
179
                                             buf + slice->offset +
180
                                             box->z * rsc->cube_map_stride,
181
                                             slice->stride,
182
                                             slice->tiling, rsc->cpp,
183
                                             &ptrans->box);
184
                }
185
                return (trans->map +
186
                        box_start_x * rsc->cpp +
187
                        box_start_y * ptrans->stride);
188
        } else {
189
                ptrans->stride = slice->stride;
190
                ptrans->layer_stride = ptrans->stride;
191
 
192
                return buf + slice->offset +
193
                        box->y / util_format_get_blockheight(format) * ptrans->stride +
194
                        box->x / util_format_get_blockwidth(format) * rsc->cpp +
195
                        box->z * rsc->cube_map_stride;
196
        }
197
 
198
 
199
fail:
200
        vc4_resource_transfer_unmap(pctx, ptrans);
201
        return NULL;
202
}
203
 
204
static void
205
vc4_resource_destroy(struct pipe_screen *pscreen,
206
                     struct pipe_resource *prsc)
207
{
208
        struct vc4_resource *rsc = vc4_resource(prsc);
209
        pipe_resource_reference(&rsc->shadow_parent, NULL);
210
        vc4_bo_unreference(&rsc->bo);
211
        free(rsc);
212
}
213
 
214
static boolean
215
vc4_resource_get_handle(struct pipe_screen *pscreen,
216
                        struct pipe_resource *prsc,
217
                        struct winsys_handle *handle)
218
{
219
        struct vc4_resource *rsc = vc4_resource(prsc);
220
 
221
        return vc4_screen_bo_get_handle(pscreen, rsc->bo, rsc->slices[0].stride,
222
                                        handle);
223
}
224
 
225
static const struct u_resource_vtbl vc4_resource_vtbl = {
226
        .resource_get_handle      = vc4_resource_get_handle,
227
        .resource_destroy         = vc4_resource_destroy,
228
        .transfer_map             = vc4_resource_transfer_map,
229
        .transfer_flush_region    = u_default_transfer_flush_region,
230
        .transfer_unmap           = vc4_resource_transfer_unmap,
231
        .transfer_inline_write    = u_default_transfer_inline_write,
232
};
233
 
234
static void
235
vc4_setup_slices(struct vc4_resource *rsc)
236
{
237
        struct pipe_resource *prsc = &rsc->base.b;
238
        uint32_t width = prsc->width0;
239
        uint32_t height = prsc->height0;
240
        uint32_t pot_width = util_next_power_of_two(width);
241
        uint32_t pot_height = util_next_power_of_two(height);
242
        uint32_t offset = 0;
243
        uint32_t utile_w = vc4_utile_width(rsc->cpp);
244
        uint32_t utile_h = vc4_utile_height(rsc->cpp);
245
 
246
        for (int i = prsc->last_level; i >= 0; i--) {
247
                struct vc4_resource_slice *slice = &rsc->slices[i];
248
 
249
                uint32_t level_width, level_height;
250
                if (i == 0) {
251
                        level_width = width;
252
                        level_height = height;
253
                } else {
254
                        level_width = u_minify(pot_width, i);
255
                        level_height = u_minify(pot_height, i);
256
                }
257
 
258
                if (!rsc->tiled) {
259
                        slice->tiling = VC4_TILING_FORMAT_LINEAR;
260
                        level_width = align(level_width, utile_w);
261
                } else {
262
                        if (vc4_size_is_lt(level_width, level_height,
263
                                           rsc->cpp)) {
264
                                slice->tiling = VC4_TILING_FORMAT_LT;
265
                                level_width = align(level_width, utile_w);
266
                                level_height = align(level_height, utile_h);
267
                        } else {
268
                                slice->tiling = VC4_TILING_FORMAT_T;
269
                                level_width = align(level_width,
270
                                                    4 * 2 * utile_w);
271
                                level_height = align(level_height,
272
                                                     4 * 2 * utile_h);
273
                        }
274
                }
275
 
276
                slice->offset = offset;
277
                slice->stride = level_width * rsc->cpp;
278
                slice->size = level_height * slice->stride;
279
 
280
                offset += slice->size;
281
 
282
                if (miptree_debug) {
283
                        static const char tiling_chars[] = {
284
                                [VC4_TILING_FORMAT_LINEAR] = 'R',
285
                                [VC4_TILING_FORMAT_LT] = 'L',
286
                                [VC4_TILING_FORMAT_T] = 'T'
287
                        };
288
                        fprintf(stderr,
289
                                "rsc setup %p (format %d), %dx%d: "
290
                                "level %d (%c) -> %dx%d, stride %d@0x%08x\n",
291
                                rsc, rsc->vc4_format,
292
                                prsc->width0, prsc->height0,
293
                                i, tiling_chars[slice->tiling],
294
                                level_width, level_height,
295
                                slice->stride, slice->offset);
296
                }
297
        }
298
 
299
        /* The texture base pointer that has to point to level 0 doesn't have
300
         * intra-page bits, so we have to align it, and thus shift up all the
301
         * smaller slices.
302
         */
303
        uint32_t page_align_offset = (align(rsc->slices[0].offset, 4096) -
304
                                      rsc->slices[0].offset);
305
        if (page_align_offset) {
306
                for (int i = 0; i <= prsc->last_level; i++)
307
                        rsc->slices[i].offset += page_align_offset;
308
        }
309
 
310
        /* Cube map faces appear as whole miptrees at a page-aligned offset
311
         * from the first face's miptree.
312
         */
313
        if (prsc->target == PIPE_TEXTURE_CUBE) {
314
                rsc->cube_map_stride = align(rsc->slices[0].offset +
315
                                             rsc->slices[0].size, 4096);
316
        }
317
}
318
 
319
static struct vc4_resource *
320
vc4_resource_setup(struct pipe_screen *pscreen,
321
                   const struct pipe_resource *tmpl)
322
{
323
        struct vc4_resource *rsc = CALLOC_STRUCT(vc4_resource);
324
        if (!rsc)
325
                return NULL;
326
        struct pipe_resource *prsc = &rsc->base.b;
327
 
328
        *prsc = *tmpl;
329
 
330
        pipe_reference_init(&prsc->reference, 1);
331
        prsc->screen = pscreen;
332
 
333
        rsc->base.vtbl = &vc4_resource_vtbl;
334
        rsc->cpp = util_format_get_blocksize(tmpl->format);
335
 
336
        assert(rsc->cpp);
337
 
338
        return rsc;
339
}
340
 
341
static enum vc4_texture_data_type
342
get_resource_texture_format(struct pipe_resource *prsc)
343
{
344
        struct vc4_resource *rsc = vc4_resource(prsc);
345
        uint8_t format = vc4_get_tex_format(prsc->format);
346
 
347
        if (!rsc->tiled) {
348
                assert(format == VC4_TEXTURE_TYPE_RGBA8888);
349
                return VC4_TEXTURE_TYPE_RGBA32R;
350
        }
351
 
352
        return format;
353
}
354
 
355
struct pipe_resource *
356
vc4_resource_create(struct pipe_screen *pscreen,
357
                    const struct pipe_resource *tmpl)
358
{
359
        struct vc4_resource *rsc = vc4_resource_setup(pscreen, tmpl);
360
        struct pipe_resource *prsc = &rsc->base.b;
361
 
362
        /* We have to make shared be untiled, since we don't have any way to
363
         * communicate metadata about tiling currently.
364
         */
365
        if (tmpl->target == PIPE_BUFFER ||
366
            (tmpl->bind & (PIPE_BIND_SCANOUT |
367
                           PIPE_BIND_LINEAR |
368
                           PIPE_BIND_SHARED |
369
                           PIPE_BIND_CURSOR))) {
370
                rsc->tiled = false;
371
        } else {
372
                rsc->tiled = true;
373
        }
374
 
375
        if (tmpl->target != PIPE_BUFFER)
376
                rsc->vc4_format = get_resource_texture_format(prsc);
377
 
378
        vc4_setup_slices(rsc);
379
        vc4_resource_bo_alloc(rsc);
380
        if (!rsc->bo)
381
                goto fail;
382
 
383
        return prsc;
384
fail:
385
        vc4_resource_destroy(pscreen, prsc);
386
        return NULL;
387
}
388
 
389
static struct pipe_resource *
390
vc4_resource_from_handle(struct pipe_screen *pscreen,
391
                         const struct pipe_resource *tmpl,
392
                         struct winsys_handle *handle)
393
{
394
        struct vc4_resource *rsc = vc4_resource_setup(pscreen, tmpl);
395
        struct pipe_resource *prsc = &rsc->base.b;
396
        struct vc4_resource_slice *slice = &rsc->slices[0];
397
 
398
        if (!rsc)
399
                return NULL;
400
 
401
        rsc->tiled = false;
402
        rsc->bo = vc4_screen_bo_from_handle(pscreen, handle);
403
        if (!rsc->bo)
404
                goto fail;
405
 
406
        if (!using_vc4_simulator)
407
                slice->stride = handle->stride;
408
        else
409
                slice->stride = align(prsc->width0 * rsc->cpp, 16);
410
 
411
        slice->tiling = VC4_TILING_FORMAT_LINEAR;
412
 
413
        rsc->vc4_format = get_resource_texture_format(prsc);
414
 
415
        if (miptree_debug) {
416
                fprintf(stderr,
417
                        "rsc import %p (format %d), %dx%d: "
418
                        "level 0 (R) -> stride %d@0x%08x\n",
419
                        rsc, rsc->vc4_format,
420
                        prsc->width0, prsc->height0,
421
                        slice->stride, slice->offset);
422
        }
423
 
424
        return prsc;
425
 
426
fail:
427
        vc4_resource_destroy(pscreen, prsc);
428
        return NULL;
429
}
430
 
431
static struct pipe_surface *
432
vc4_create_surface(struct pipe_context *pctx,
433
                   struct pipe_resource *ptex,
434
                   const struct pipe_surface *surf_tmpl)
435
{
436
        struct vc4_surface *surface = CALLOC_STRUCT(vc4_surface);
437
        struct vc4_resource *rsc = vc4_resource(ptex);
438
 
439
        if (!surface)
440
                return NULL;
441
 
442
        assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
443
 
444
        struct pipe_surface *psurf = &surface->base;
445
        unsigned level = surf_tmpl->u.tex.level;
446
 
447
        pipe_reference_init(&psurf->reference, 1);
448
        pipe_resource_reference(&psurf->texture, ptex);
449
 
450
        psurf->context = pctx;
451
        psurf->format = surf_tmpl->format;
452
        psurf->width = u_minify(ptex->width0, level);
453
        psurf->height = u_minify(ptex->height0, level);
454
        psurf->u.tex.level = level;
455
        psurf->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
456
        psurf->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
457
        surface->offset = rsc->slices[level].offset;
458
        surface->tiling = rsc->slices[level].tiling;
459
 
460
        return &surface->base;
461
}
462
 
463
static void
464
vc4_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf)
465
{
466
        pipe_resource_reference(&psurf->texture, NULL);
467
        FREE(psurf);
468
}
469
 
470
/** Debug routine to dump the contents of an 8888 surface to the console */
471
void
472
vc4_dump_surface(struct pipe_surface *psurf)
473
{
474
        if (!psurf)
475
                return;
476
 
477
        struct pipe_resource *prsc = psurf->texture;
478
        struct vc4_resource *rsc = vc4_resource(prsc);
479
        uint32_t *map = vc4_bo_map(rsc->bo);
480
        uint32_t stride = rsc->slices[0].stride / 4;
481
        uint32_t width = psurf->width;
482
        uint32_t height = psurf->height;
483
        uint32_t chunk_w = width / 79;
484
        uint32_t chunk_h = height / 40;
485
        uint32_t found_colors[10];
486
        uint32_t num_found_colors = 0;
487
 
488
        if (rsc->vc4_format != VC4_TEXTURE_TYPE_RGBA32R) {
489
                fprintf(stderr, "%s: Unsupported format %s\n",
490
                        __func__, util_format_short_name(psurf->format));
491
                return;
492
        }
493
 
494
        for (int by = 0; by < height; by += chunk_h) {
495
                for (int bx = 0; bx < width; bx += chunk_w) {
496
                        int all_found_color = -1; /* nothing found */
497
 
498
                        for (int y = by; y < MIN2(height, by + chunk_h); y++) {
499
                                for (int x = bx; x < MIN2(width, bx + chunk_w); x++) {
500
                                        uint32_t pix = map[y * stride + x];
501
 
502
                                        int i;
503
                                        for (i = 0; i < num_found_colors; i++) {
504
                                                if (pix == found_colors[i])
505
                                                        break;
506
                                        }
507
                                        if (i == num_found_colors &&
508
                                            num_found_colors <
509
                                            ARRAY_SIZE(found_colors)) {
510
                                                found_colors[num_found_colors++] = pix;
511
                                        }
512
 
513
                                        if (i < num_found_colors) {
514
                                                if (all_found_color == -1)
515
                                                        all_found_color = i;
516
                                                else if (i != all_found_color)
517
                                                        all_found_color = ARRAY_SIZE(found_colors);
518
                                        }
519
                                }
520
                        }
521
                        /* If all pixels for this chunk have a consistent
522
                         * value, then print a character for it.  Either a
523
                         * fixed name (particularly common for piglit tests),
524
                         * or a runtime-generated number.
525
                         */
526
                        if (all_found_color >= 0 &&
527
                            all_found_color < ARRAY_SIZE(found_colors)) {
528
                                static const struct {
529
                                        uint32_t val;
530
                                        const char *c;
531
                                } named_colors[] = {
532
                                        { 0xff000000, "█" },
533
                                        { 0x00000000, "█" },
534
                                        { 0xffff0000, "r" },
535
                                        { 0xff00ff00, "g" },
536
                                        { 0xff0000ff, "b" },
537
                                        { 0xffffffff, "w" },
538
                                };
539
                                int i;
540
                                for (i = 0; i < ARRAY_SIZE(named_colors); i++) {
541
                                        if (named_colors[i].val ==
542
                                            found_colors[all_found_color]) {
543
                                                fprintf(stderr, "%s",
544
                                                        named_colors[i].c);
545
                                                break;
546
                                        }
547
                                }
548
                                /* For unnamed colors, print a number and the
549
                                 * numbers will have values printed at the
550
                                 * end.
551
                                 */
552
                                if (i == ARRAY_SIZE(named_colors)) {
553
                                        fprintf(stderr, "%c",
554
                                                '0' + all_found_color);
555
                                }
556
                        } else {
557
                                /* If there's no consistent color, print this.
558
                                 */
559
                                fprintf(stderr, ".");
560
                        }
561
                }
562
                fprintf(stderr, "\n");
563
        }
564
 
565
        for (int i = 0; i < num_found_colors; i++) {
566
                fprintf(stderr, "color %d: 0x%08x\n", i, found_colors[i]);
567
        }
568
}
569
 
570
static void
571
vc4_flush_resource(struct pipe_context *pctx, struct pipe_resource *resource)
572
{
573
        /* All calls to flush_resource are followed by a flush of the context,
574
         * so there's nothing to do.
575
         */
576
}
577
 
578
void
579
vc4_update_shadow_baselevel_texture(struct pipe_context *pctx,
580
                                    struct pipe_sampler_view *view)
581
{
582
        struct vc4_resource *shadow = vc4_resource(view->texture);
583
        struct vc4_resource *orig = vc4_resource(shadow->shadow_parent);
584
        assert(orig);
585
 
586
        if (shadow->writes == orig->writes && orig->bo->private)
587
                return;
588
 
589
        perf_debug("Updating shadow texture due to %s\n",
590
                   view->u.tex.first_level ? "base level" : "raster layout");
591
 
592
        for (int i = 0; i <= shadow->base.b.last_level; i++) {
593
                unsigned width = u_minify(shadow->base.b.width0, i);
594
                unsigned height = u_minify(shadow->base.b.height0, i);
595
                struct pipe_blit_info info = {
596
                        .dst = {
597
                                .resource = &shadow->base.b,
598
                                .level = i,
599
                                .box = {
600
                                        .x = 0,
601
                                        .y = 0,
602
                                        .z = 0,
603
                                        .width = width,
604
                                        .height = height,
605
                                        .depth = 1,
606
                                },
607
                                .format = shadow->base.b.format,
608
                        },
609
                        .src = {
610
                                .resource = &orig->base.b,
611
                                .level = view->u.tex.first_level + i,
612
                                .box = {
613
                                        .x = 0,
614
                                        .y = 0,
615
                                        .z = 0,
616
                                        .width = width,
617
                                        .height = height,
618
                                        .depth = 1,
619
                                },
620
                                .format = orig->base.b.format,
621
                        },
622
                        .mask = ~0,
623
                };
624
                pctx->blit(pctx, &info);
625
        }
626
 
627
        shadow->writes = orig->writes;
628
}
629
 
630
/**
631
 * Converts a 4-byte index buffer to 2 bytes.
632
 *
633
 * Since GLES2 only has support for 1 and 2-byte indices, the hardware doesn't
634
 * include 4-byte index support, and we have to shrink it down.
635
 *
636
 * There's no fallback support for when indices end up being larger than 2^16,
637
 * though it will at least assertion fail.  Also, if the original index data
638
 * was in user memory, it would be nice to not have uploaded it to a VBO
639
 * before translating.
640
 */
641
void
642
vc4_update_shadow_index_buffer(struct pipe_context *pctx,
643
                               const struct pipe_index_buffer *ib)
644
{
645
        struct vc4_resource *shadow = vc4_resource(ib->buffer);
646
        struct vc4_resource *orig = vc4_resource(shadow->shadow_parent);
647
        uint32_t count = shadow->base.b.width0 / 2;
648
 
649
        if (shadow->writes == orig->writes)
650
                return;
651
 
652
        perf_debug("Fallback conversion for %d uint indices\n", count);
653
 
654
        struct pipe_transfer *src_transfer;
655
        uint32_t *src = pipe_buffer_map_range(pctx, &orig->base.b,
656
                                              ib->offset,
657
                                              count * 4,
658
                                              PIPE_TRANSFER_READ, &src_transfer);
659
 
660
        struct pipe_transfer *dst_transfer;
661
        uint16_t *dst = pipe_buffer_map_range(pctx, &shadow->base.b,
662
                                              0,
663
                                              count * 2,
664
                                              PIPE_TRANSFER_WRITE, &dst_transfer);
665
 
666
        for (int i = 0; i < count; i++) {
667
                uint32_t src_index = src[i];
668
                assert(src_index <= 0xffff);
669
                dst[i] = src_index;
670
        }
671
 
672
        pctx->transfer_unmap(pctx, dst_transfer);
673
        pctx->transfer_unmap(pctx, src_transfer);
674
 
675
        shadow->writes = orig->writes;
676
}
677
 
678
void
679
vc4_resource_screen_init(struct pipe_screen *pscreen)
680
{
681
        pscreen->resource_create = vc4_resource_create;
682
        pscreen->resource_from_handle = vc4_resource_from_handle;
683
        pscreen->resource_get_handle = u_resource_get_handle_vtbl;
684
        pscreen->resource_destroy = u_resource_destroy_vtbl;
685
}
686
 
687
void
688
vc4_resource_context_init(struct pipe_context *pctx)
689
{
690
        pctx->transfer_map = u_transfer_map_vtbl;
691
        pctx->transfer_flush_region = u_transfer_flush_region_vtbl;
692
        pctx->transfer_unmap = u_transfer_unmap_vtbl;
693
        pctx->transfer_inline_write = u_transfer_inline_write_vtbl;
694
        pctx->create_surface = vc4_create_surface;
695
        pctx->surface_destroy = vc4_surface_destroy;
696
        pctx->resource_copy_region = util_resource_copy_region;
697
        pctx->blit = vc4_blit;
698
        pctx->flush_resource = vc4_flush_resource;
699
}