1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2014 Broadcom 3bf215546Sopenharmony_ci * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org> 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22bf215546Sopenharmony_ci * IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "pipe/p_defines.h" 26bf215546Sopenharmony_ci#include "util/u_memory.h" 27bf215546Sopenharmony_ci#include "util/format/u_format.h" 28bf215546Sopenharmony_ci#include "util/u_inlines.h" 29bf215546Sopenharmony_ci#include "util/u_surface.h" 30bf215546Sopenharmony_ci#include "util/u_transfer_helper.h" 31bf215546Sopenharmony_ci#include "util/u_upload_mgr.h" 32bf215546Sopenharmony_ci#include "util/u_drm.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "drm-uapi/drm_fourcc.h" 35bf215546Sopenharmony_ci#include "drm-uapi/vc4_drm.h" 36bf215546Sopenharmony_ci#include "vc4_screen.h" 37bf215546Sopenharmony_ci#include "vc4_context.h" 38bf215546Sopenharmony_ci#include "vc4_resource.h" 39bf215546Sopenharmony_ci#include "vc4_tiling.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_cistatic bool 42bf215546Sopenharmony_civc4_resource_bo_alloc(struct vc4_resource *rsc) 43bf215546Sopenharmony_ci{ 44bf215546Sopenharmony_ci struct pipe_resource *prsc = &rsc->base; 45bf215546Sopenharmony_ci struct pipe_screen *pscreen = prsc->screen; 46bf215546Sopenharmony_ci struct vc4_bo *bo; 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci if (vc4_debug & VC4_DEBUG_SURFACE) { 49bf215546Sopenharmony_ci fprintf(stderr, "alloc %p: size %d + offset %d -> %d\n", 50bf215546Sopenharmony_ci rsc, 51bf215546Sopenharmony_ci rsc->slices[0].size, 52bf215546Sopenharmony_ci rsc->slices[0].offset, 53bf215546Sopenharmony_ci rsc->slices[0].offset + 54bf215546Sopenharmony_ci rsc->slices[0].size + 55bf215546Sopenharmony_ci rsc->cube_map_stride * (prsc->array_size - 1)); 56bf215546Sopenharmony_ci } 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci bo = vc4_bo_alloc(vc4_screen(pscreen), 59bf215546Sopenharmony_ci rsc->slices[0].offset + 60bf215546Sopenharmony_ci rsc->slices[0].size + 61bf215546Sopenharmony_ci rsc->cube_map_stride * (prsc->array_size - 1), 62bf215546Sopenharmony_ci "resource"); 63bf215546Sopenharmony_ci if (bo) { 64bf215546Sopenharmony_ci vc4_bo_unreference(&rsc->bo); 65bf215546Sopenharmony_ci rsc->bo = bo; 66bf215546Sopenharmony_ci return true; 67bf215546Sopenharmony_ci } else { 68bf215546Sopenharmony_ci return false; 69bf215546Sopenharmony_ci } 70bf215546Sopenharmony_ci} 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_cistatic void 73bf215546Sopenharmony_civc4_resource_transfer_unmap(struct pipe_context *pctx, 74bf215546Sopenharmony_ci struct pipe_transfer *ptrans) 75bf215546Sopenharmony_ci{ 76bf215546Sopenharmony_ci struct vc4_context *vc4 = vc4_context(pctx); 77bf215546Sopenharmony_ci struct vc4_transfer *trans = vc4_transfer(ptrans); 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci if (trans->map) { 80bf215546Sopenharmony_ci struct vc4_resource *rsc = vc4_resource(ptrans->resource); 81bf215546Sopenharmony_ci struct vc4_resource_slice *slice = &rsc->slices[ptrans->level]; 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci if (ptrans->usage & PIPE_MAP_WRITE) { 84bf215546Sopenharmony_ci vc4_store_tiled_image(rsc->bo->map + slice->offset + 85bf215546Sopenharmony_ci ptrans->box.z * rsc->cube_map_stride, 86bf215546Sopenharmony_ci slice->stride, 87bf215546Sopenharmony_ci trans->map, ptrans->stride, 88bf215546Sopenharmony_ci slice->tiling, rsc->cpp, 89bf215546Sopenharmony_ci &ptrans->box); 90bf215546Sopenharmony_ci } 91bf215546Sopenharmony_ci free(trans->map); 92bf215546Sopenharmony_ci } 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci pipe_resource_reference(&ptrans->resource, NULL); 95bf215546Sopenharmony_ci slab_free(&vc4->transfer_pool, ptrans); 96bf215546Sopenharmony_ci} 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_cistatic void * 99bf215546Sopenharmony_civc4_resource_transfer_map(struct pipe_context *pctx, 100bf215546Sopenharmony_ci struct pipe_resource *prsc, 101bf215546Sopenharmony_ci unsigned level, unsigned usage, 102bf215546Sopenharmony_ci const struct pipe_box *box, 103bf215546Sopenharmony_ci struct pipe_transfer **pptrans) 104bf215546Sopenharmony_ci{ 105bf215546Sopenharmony_ci struct vc4_context *vc4 = vc4_context(pctx); 106bf215546Sopenharmony_ci struct vc4_resource *rsc = vc4_resource(prsc); 107bf215546Sopenharmony_ci struct vc4_transfer *trans; 108bf215546Sopenharmony_ci struct pipe_transfer *ptrans; 109bf215546Sopenharmony_ci enum pipe_format format = prsc->format; 110bf215546Sopenharmony_ci char *buf; 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci /* Upgrade DISCARD_RANGE to WHOLE_RESOURCE if the whole resource is 113bf215546Sopenharmony_ci * being mapped. 114bf215546Sopenharmony_ci */ 115bf215546Sopenharmony_ci if ((usage & PIPE_MAP_DISCARD_RANGE) && 116bf215546Sopenharmony_ci !(usage & PIPE_MAP_UNSYNCHRONIZED) && 117bf215546Sopenharmony_ci !(prsc->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) && 118bf215546Sopenharmony_ci prsc->last_level == 0 && 119bf215546Sopenharmony_ci prsc->width0 == box->width && 120bf215546Sopenharmony_ci prsc->height0 == box->height && 121bf215546Sopenharmony_ci prsc->depth0 == box->depth && 122bf215546Sopenharmony_ci prsc->array_size == 1 && 123bf215546Sopenharmony_ci rsc->bo->private) { 124bf215546Sopenharmony_ci usage |= PIPE_MAP_DISCARD_WHOLE_RESOURCE; 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci if (usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE) { 128bf215546Sopenharmony_ci if (vc4_resource_bo_alloc(rsc)) { 129bf215546Sopenharmony_ci /* If it might be bound as one of our vertex buffers, 130bf215546Sopenharmony_ci * make sure we re-emit vertex buffer state. 131bf215546Sopenharmony_ci */ 132bf215546Sopenharmony_ci if (prsc->bind & PIPE_BIND_VERTEX_BUFFER) 133bf215546Sopenharmony_ci vc4->dirty |= VC4_DIRTY_VTXBUF; 134bf215546Sopenharmony_ci } else { 135bf215546Sopenharmony_ci /* If we failed to reallocate, flush users so that we 136bf215546Sopenharmony_ci * don't violate any syncing requirements. 137bf215546Sopenharmony_ci */ 138bf215546Sopenharmony_ci vc4_flush_jobs_reading_resource(vc4, prsc); 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci } else if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) { 141bf215546Sopenharmony_ci /* If we're writing and the buffer is being used by the CL, we 142bf215546Sopenharmony_ci * have to flush the CL first. If we're only reading, we need 143bf215546Sopenharmony_ci * to flush if the CL has written our buffer. 144bf215546Sopenharmony_ci */ 145bf215546Sopenharmony_ci if (usage & PIPE_MAP_WRITE) 146bf215546Sopenharmony_ci vc4_flush_jobs_reading_resource(vc4, prsc); 147bf215546Sopenharmony_ci else 148bf215546Sopenharmony_ci vc4_flush_jobs_writing_resource(vc4, prsc); 149bf215546Sopenharmony_ci } 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci if (usage & PIPE_MAP_WRITE) { 152bf215546Sopenharmony_ci rsc->writes++; 153bf215546Sopenharmony_ci rsc->initialized_buffers = ~0; 154bf215546Sopenharmony_ci } 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci trans = slab_zalloc(&vc4->transfer_pool); 157bf215546Sopenharmony_ci if (!trans) 158bf215546Sopenharmony_ci return NULL; 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci /* XXX: Handle DONTBLOCK, DISCARD_RANGE, PERSISTENT, COHERENT. */ 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci ptrans = &trans->base; 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci pipe_resource_reference(&ptrans->resource, prsc); 165bf215546Sopenharmony_ci ptrans->level = level; 166bf215546Sopenharmony_ci ptrans->usage = usage; 167bf215546Sopenharmony_ci ptrans->box = *box; 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci if (usage & PIPE_MAP_UNSYNCHRONIZED) 170bf215546Sopenharmony_ci buf = vc4_bo_map_unsynchronized(rsc->bo); 171bf215546Sopenharmony_ci else 172bf215546Sopenharmony_ci buf = vc4_bo_map(rsc->bo); 173bf215546Sopenharmony_ci if (!buf) { 174bf215546Sopenharmony_ci fprintf(stderr, "Failed to map bo\n"); 175bf215546Sopenharmony_ci goto fail; 176bf215546Sopenharmony_ci } 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci *pptrans = ptrans; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci struct vc4_resource_slice *slice = &rsc->slices[level]; 181bf215546Sopenharmony_ci if (rsc->tiled) { 182bf215546Sopenharmony_ci /* No direct mappings of tiled, since we need to manually 183bf215546Sopenharmony_ci * tile/untile. 184bf215546Sopenharmony_ci */ 185bf215546Sopenharmony_ci if (usage & PIPE_MAP_DIRECTLY) 186bf215546Sopenharmony_ci return NULL; 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci /* Our load/store routines work on entire compressed blocks. */ 189bf215546Sopenharmony_ci u_box_pixels_to_blocks(&ptrans->box, &ptrans->box, format); 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci ptrans->stride = ptrans->box.width * rsc->cpp; 192bf215546Sopenharmony_ci ptrans->layer_stride = ptrans->stride * ptrans->box.height; 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci trans->map = malloc(ptrans->layer_stride * ptrans->box.depth); 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci if (usage & PIPE_MAP_READ) { 197bf215546Sopenharmony_ci vc4_load_tiled_image(trans->map, ptrans->stride, 198bf215546Sopenharmony_ci buf + slice->offset + 199bf215546Sopenharmony_ci ptrans->box.z * rsc->cube_map_stride, 200bf215546Sopenharmony_ci slice->stride, 201bf215546Sopenharmony_ci slice->tiling, rsc->cpp, 202bf215546Sopenharmony_ci &ptrans->box); 203bf215546Sopenharmony_ci } 204bf215546Sopenharmony_ci return trans->map; 205bf215546Sopenharmony_ci } else { 206bf215546Sopenharmony_ci ptrans->stride = slice->stride; 207bf215546Sopenharmony_ci ptrans->layer_stride = ptrans->stride; 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci return buf + slice->offset + 210bf215546Sopenharmony_ci ptrans->box.y / util_format_get_blockheight(format) * ptrans->stride + 211bf215546Sopenharmony_ci ptrans->box.x / util_format_get_blockwidth(format) * rsc->cpp + 212bf215546Sopenharmony_ci ptrans->box.z * rsc->cube_map_stride; 213bf215546Sopenharmony_ci } 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_cifail: 217bf215546Sopenharmony_ci vc4_resource_transfer_unmap(pctx, ptrans); 218bf215546Sopenharmony_ci return NULL; 219bf215546Sopenharmony_ci} 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_cistatic void 222bf215546Sopenharmony_civc4_texture_subdata(struct pipe_context *pctx, 223bf215546Sopenharmony_ci struct pipe_resource *prsc, 224bf215546Sopenharmony_ci unsigned level, 225bf215546Sopenharmony_ci unsigned usage, 226bf215546Sopenharmony_ci const struct pipe_box *box, 227bf215546Sopenharmony_ci const void *data, 228bf215546Sopenharmony_ci unsigned stride, 229bf215546Sopenharmony_ci unsigned layer_stride) 230bf215546Sopenharmony_ci{ 231bf215546Sopenharmony_ci struct vc4_resource *rsc = vc4_resource(prsc); 232bf215546Sopenharmony_ci struct vc4_resource_slice *slice = &rsc->slices[level]; 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci /* For a direct mapping, we can just take the u_transfer path. */ 235bf215546Sopenharmony_ci if (!rsc->tiled || 236bf215546Sopenharmony_ci box->depth != 1 || 237bf215546Sopenharmony_ci (usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE)) { 238bf215546Sopenharmony_ci return u_default_texture_subdata(pctx, prsc, level, usage, box, 239bf215546Sopenharmony_ci data, stride, layer_stride); 240bf215546Sopenharmony_ci } 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci /* Otherwise, map and store the texture data directly into the tiled 243bf215546Sopenharmony_ci * texture. 244bf215546Sopenharmony_ci */ 245bf215546Sopenharmony_ci void *buf; 246bf215546Sopenharmony_ci if (usage & PIPE_MAP_UNSYNCHRONIZED) 247bf215546Sopenharmony_ci buf = vc4_bo_map_unsynchronized(rsc->bo); 248bf215546Sopenharmony_ci else 249bf215546Sopenharmony_ci buf = vc4_bo_map(rsc->bo); 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci vc4_store_tiled_image(buf + slice->offset + 252bf215546Sopenharmony_ci box->z * rsc->cube_map_stride, 253bf215546Sopenharmony_ci slice->stride, 254bf215546Sopenharmony_ci (void *)data, stride, 255bf215546Sopenharmony_ci slice->tiling, rsc->cpp, 256bf215546Sopenharmony_ci box); 257bf215546Sopenharmony_ci} 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_cistatic void 260bf215546Sopenharmony_civc4_resource_destroy(struct pipe_screen *pscreen, 261bf215546Sopenharmony_ci struct pipe_resource *prsc) 262bf215546Sopenharmony_ci{ 263bf215546Sopenharmony_ci struct vc4_screen *screen = vc4_screen(pscreen); 264bf215546Sopenharmony_ci struct vc4_resource *rsc = vc4_resource(prsc); 265bf215546Sopenharmony_ci vc4_bo_unreference(&rsc->bo); 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci if (rsc->scanout) 268bf215546Sopenharmony_ci renderonly_scanout_destroy(rsc->scanout, screen->ro); 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci free(rsc); 271bf215546Sopenharmony_ci} 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_cistatic uint64_t 274bf215546Sopenharmony_civc4_resource_modifier(struct vc4_resource *rsc) 275bf215546Sopenharmony_ci{ 276bf215546Sopenharmony_ci if (rsc->tiled) 277bf215546Sopenharmony_ci return DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED; 278bf215546Sopenharmony_ci else 279bf215546Sopenharmony_ci return DRM_FORMAT_MOD_LINEAR; 280bf215546Sopenharmony_ci} 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_cistatic bool 283bf215546Sopenharmony_civc4_resource_get_handle(struct pipe_screen *pscreen, 284bf215546Sopenharmony_ci struct pipe_context *pctx, 285bf215546Sopenharmony_ci struct pipe_resource *prsc, 286bf215546Sopenharmony_ci struct winsys_handle *whandle, 287bf215546Sopenharmony_ci unsigned usage) 288bf215546Sopenharmony_ci{ 289bf215546Sopenharmony_ci struct vc4_screen *screen = vc4_screen(pscreen); 290bf215546Sopenharmony_ci struct vc4_resource *rsc = vc4_resource(prsc); 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci whandle->stride = rsc->slices[0].stride; 293bf215546Sopenharmony_ci whandle->offset = 0; 294bf215546Sopenharmony_ci whandle->modifier = vc4_resource_modifier(rsc); 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci /* If we're passing some reference to our BO out to some other part of 297bf215546Sopenharmony_ci * the system, then we can't do any optimizations about only us being 298bf215546Sopenharmony_ci * the ones seeing it (like BO caching or shadow update avoidance). 299bf215546Sopenharmony_ci */ 300bf215546Sopenharmony_ci rsc->bo->private = false; 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci switch (whandle->type) { 303bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_SHARED: 304bf215546Sopenharmony_ci if (screen->ro) { 305bf215546Sopenharmony_ci /* This could probably be supported, assuming that a 306bf215546Sopenharmony_ci * control node was used for pl111. 307bf215546Sopenharmony_ci */ 308bf215546Sopenharmony_ci fprintf(stderr, "flink unsupported with pl111\n"); 309bf215546Sopenharmony_ci return false; 310bf215546Sopenharmony_ci } 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci return vc4_bo_flink(rsc->bo, &whandle->handle); 313bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_KMS: 314bf215546Sopenharmony_ci if (screen->ro) { 315bf215546Sopenharmony_ci return renderonly_get_handle(rsc->scanout, whandle); 316bf215546Sopenharmony_ci } 317bf215546Sopenharmony_ci whandle->handle = rsc->bo->handle; 318bf215546Sopenharmony_ci return true; 319bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_FD: 320bf215546Sopenharmony_ci /* FDs are cross-device, so we can export directly from vc4. 321bf215546Sopenharmony_ci */ 322bf215546Sopenharmony_ci whandle->handle = vc4_bo_get_dmabuf(rsc->bo); 323bf215546Sopenharmony_ci return whandle->handle != -1; 324bf215546Sopenharmony_ci } 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci return false; 327bf215546Sopenharmony_ci} 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_cistatic bool 330bf215546Sopenharmony_civc4_resource_get_param(struct pipe_screen *pscreen, 331bf215546Sopenharmony_ci struct pipe_context *pctx, struct pipe_resource *prsc, 332bf215546Sopenharmony_ci unsigned plane, unsigned layer, unsigned level, 333bf215546Sopenharmony_ci enum pipe_resource_param param, 334bf215546Sopenharmony_ci unsigned usage, uint64_t *value) 335bf215546Sopenharmony_ci{ 336bf215546Sopenharmony_ci struct vc4_resource *rsc = vc4_resource(prsc); 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci switch (param) { 339bf215546Sopenharmony_ci case PIPE_RESOURCE_PARAM_STRIDE: 340bf215546Sopenharmony_ci *value = rsc->slices[level].stride; 341bf215546Sopenharmony_ci return true; 342bf215546Sopenharmony_ci case PIPE_RESOURCE_PARAM_OFFSET: 343bf215546Sopenharmony_ci *value = 0; 344bf215546Sopenharmony_ci return true; 345bf215546Sopenharmony_ci case PIPE_RESOURCE_PARAM_MODIFIER: 346bf215546Sopenharmony_ci *value = vc4_resource_modifier(rsc); 347bf215546Sopenharmony_ci return true; 348bf215546Sopenharmony_ci default: 349bf215546Sopenharmony_ci return false; 350bf215546Sopenharmony_ci } 351bf215546Sopenharmony_ci} 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_cistatic void 354bf215546Sopenharmony_civc4_setup_slices(struct vc4_resource *rsc, const char *caller) 355bf215546Sopenharmony_ci{ 356bf215546Sopenharmony_ci struct pipe_resource *prsc = &rsc->base; 357bf215546Sopenharmony_ci uint32_t width = prsc->width0; 358bf215546Sopenharmony_ci uint32_t height = prsc->height0; 359bf215546Sopenharmony_ci if (prsc->format == PIPE_FORMAT_ETC1_RGB8) { 360bf215546Sopenharmony_ci width = (width + 3) >> 2; 361bf215546Sopenharmony_ci height = (height + 3) >> 2; 362bf215546Sopenharmony_ci } 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_ci uint32_t pot_width = util_next_power_of_two(width); 365bf215546Sopenharmony_ci uint32_t pot_height = util_next_power_of_two(height); 366bf215546Sopenharmony_ci uint32_t offset = 0; 367bf215546Sopenharmony_ci uint32_t utile_w = vc4_utile_width(rsc->cpp); 368bf215546Sopenharmony_ci uint32_t utile_h = vc4_utile_height(rsc->cpp); 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci for (int i = prsc->last_level; i >= 0; i--) { 371bf215546Sopenharmony_ci struct vc4_resource_slice *slice = &rsc->slices[i]; 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci uint32_t level_width, level_height; 374bf215546Sopenharmony_ci if (i == 0) { 375bf215546Sopenharmony_ci level_width = width; 376bf215546Sopenharmony_ci level_height = height; 377bf215546Sopenharmony_ci } else { 378bf215546Sopenharmony_ci level_width = u_minify(pot_width, i); 379bf215546Sopenharmony_ci level_height = u_minify(pot_height, i); 380bf215546Sopenharmony_ci } 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci if (!rsc->tiled) { 383bf215546Sopenharmony_ci slice->tiling = VC4_TILING_FORMAT_LINEAR; 384bf215546Sopenharmony_ci if (prsc->nr_samples > 1) { 385bf215546Sopenharmony_ci /* MSAA (4x) surfaces are stored as raw tile buffer contents. */ 386bf215546Sopenharmony_ci level_width = align(level_width, 32); 387bf215546Sopenharmony_ci level_height = align(level_height, 32); 388bf215546Sopenharmony_ci } else { 389bf215546Sopenharmony_ci level_width = align(level_width, utile_w); 390bf215546Sopenharmony_ci } 391bf215546Sopenharmony_ci } else { 392bf215546Sopenharmony_ci if (vc4_size_is_lt(level_width, level_height, 393bf215546Sopenharmony_ci rsc->cpp)) { 394bf215546Sopenharmony_ci slice->tiling = VC4_TILING_FORMAT_LT; 395bf215546Sopenharmony_ci level_width = align(level_width, utile_w); 396bf215546Sopenharmony_ci level_height = align(level_height, utile_h); 397bf215546Sopenharmony_ci } else { 398bf215546Sopenharmony_ci slice->tiling = VC4_TILING_FORMAT_T; 399bf215546Sopenharmony_ci level_width = align(level_width, 400bf215546Sopenharmony_ci 4 * 2 * utile_w); 401bf215546Sopenharmony_ci level_height = align(level_height, 402bf215546Sopenharmony_ci 4 * 2 * utile_h); 403bf215546Sopenharmony_ci } 404bf215546Sopenharmony_ci } 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci slice->offset = offset; 407bf215546Sopenharmony_ci slice->stride = (level_width * rsc->cpp * 408bf215546Sopenharmony_ci MAX2(prsc->nr_samples, 1)); 409bf215546Sopenharmony_ci slice->size = level_height * slice->stride; 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci offset += slice->size; 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_ci if (vc4_debug & VC4_DEBUG_SURFACE) { 414bf215546Sopenharmony_ci static const char tiling_chars[] = { 415bf215546Sopenharmony_ci [VC4_TILING_FORMAT_LINEAR] = 'R', 416bf215546Sopenharmony_ci [VC4_TILING_FORMAT_LT] = 'L', 417bf215546Sopenharmony_ci [VC4_TILING_FORMAT_T] = 'T' 418bf215546Sopenharmony_ci }; 419bf215546Sopenharmony_ci fprintf(stderr, 420bf215546Sopenharmony_ci "rsc %s %p (format %s: vc4 %d), %dx%d: " 421bf215546Sopenharmony_ci "level %d (%c) -> %dx%d, stride %d@0x%08x\n", 422bf215546Sopenharmony_ci caller, rsc, 423bf215546Sopenharmony_ci util_format_short_name(prsc->format), 424bf215546Sopenharmony_ci rsc->vc4_format, 425bf215546Sopenharmony_ci prsc->width0, prsc->height0, 426bf215546Sopenharmony_ci i, tiling_chars[slice->tiling], 427bf215546Sopenharmony_ci level_width, level_height, 428bf215546Sopenharmony_ci slice->stride, slice->offset); 429bf215546Sopenharmony_ci } 430bf215546Sopenharmony_ci } 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_ci /* The texture base pointer that has to point to level 0 doesn't have 433bf215546Sopenharmony_ci * intra-page bits, so we have to align it, and thus shift up all the 434bf215546Sopenharmony_ci * smaller slices. 435bf215546Sopenharmony_ci */ 436bf215546Sopenharmony_ci uint32_t page_align_offset = (align(rsc->slices[0].offset, 4096) - 437bf215546Sopenharmony_ci rsc->slices[0].offset); 438bf215546Sopenharmony_ci if (page_align_offset) { 439bf215546Sopenharmony_ci for (int i = 0; i <= prsc->last_level; i++) 440bf215546Sopenharmony_ci rsc->slices[i].offset += page_align_offset; 441bf215546Sopenharmony_ci } 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci /* Cube map faces appear as whole miptrees at a page-aligned offset 444bf215546Sopenharmony_ci * from the first face's miptree. 445bf215546Sopenharmony_ci */ 446bf215546Sopenharmony_ci if (prsc->target == PIPE_TEXTURE_CUBE) { 447bf215546Sopenharmony_ci rsc->cube_map_stride = align(rsc->slices[0].offset + 448bf215546Sopenharmony_ci rsc->slices[0].size, 4096); 449bf215546Sopenharmony_ci } 450bf215546Sopenharmony_ci} 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_cistatic struct vc4_resource * 453bf215546Sopenharmony_civc4_resource_setup(struct pipe_screen *pscreen, 454bf215546Sopenharmony_ci const struct pipe_resource *tmpl) 455bf215546Sopenharmony_ci{ 456bf215546Sopenharmony_ci struct vc4_resource *rsc = CALLOC_STRUCT(vc4_resource); 457bf215546Sopenharmony_ci if (!rsc) 458bf215546Sopenharmony_ci return NULL; 459bf215546Sopenharmony_ci struct pipe_resource *prsc = &rsc->base; 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci *prsc = *tmpl; 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci pipe_reference_init(&prsc->reference, 1); 464bf215546Sopenharmony_ci prsc->screen = pscreen; 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci if (prsc->nr_samples <= 1) 467bf215546Sopenharmony_ci rsc->cpp = util_format_get_blocksize(tmpl->format); 468bf215546Sopenharmony_ci else 469bf215546Sopenharmony_ci rsc->cpp = sizeof(uint32_t); 470bf215546Sopenharmony_ci 471bf215546Sopenharmony_ci assert(rsc->cpp); 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci return rsc; 474bf215546Sopenharmony_ci} 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_cistatic enum vc4_texture_data_type 477bf215546Sopenharmony_ciget_resource_texture_format(struct pipe_resource *prsc) 478bf215546Sopenharmony_ci{ 479bf215546Sopenharmony_ci struct vc4_resource *rsc = vc4_resource(prsc); 480bf215546Sopenharmony_ci uint8_t format = vc4_get_tex_format(prsc->format); 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci if (!rsc->tiled) { 483bf215546Sopenharmony_ci if (prsc->nr_samples > 1) { 484bf215546Sopenharmony_ci return ~0; 485bf215546Sopenharmony_ci } else { 486bf215546Sopenharmony_ci if (format == VC4_TEXTURE_TYPE_RGBA8888) 487bf215546Sopenharmony_ci return VC4_TEXTURE_TYPE_RGBA32R; 488bf215546Sopenharmony_ci else 489bf215546Sopenharmony_ci return ~0; 490bf215546Sopenharmony_ci } 491bf215546Sopenharmony_ci } 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci return format; 494bf215546Sopenharmony_ci} 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_cistatic struct pipe_resource * 497bf215546Sopenharmony_civc4_resource_create_with_modifiers(struct pipe_screen *pscreen, 498bf215546Sopenharmony_ci const struct pipe_resource *tmpl, 499bf215546Sopenharmony_ci const uint64_t *modifiers, 500bf215546Sopenharmony_ci int count) 501bf215546Sopenharmony_ci{ 502bf215546Sopenharmony_ci struct vc4_screen *screen = vc4_screen(pscreen); 503bf215546Sopenharmony_ci struct vc4_resource *rsc = vc4_resource_setup(pscreen, tmpl); 504bf215546Sopenharmony_ci struct pipe_resource *prsc = &rsc->base; 505bf215546Sopenharmony_ci bool linear_ok = drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count); 506bf215546Sopenharmony_ci /* Use a tiled layout if we can, for better 3D performance. */ 507bf215546Sopenharmony_ci bool should_tile = true; 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci /* VBOs/PBOs are untiled (and 1 height). */ 510bf215546Sopenharmony_ci if (tmpl->target == PIPE_BUFFER) 511bf215546Sopenharmony_ci should_tile = false; 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci /* MSAA buffers are linear. */ 514bf215546Sopenharmony_ci if (tmpl->nr_samples > 1) 515bf215546Sopenharmony_ci should_tile = false; 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci /* No tiling when we're sharing with another device (pl111). */ 518bf215546Sopenharmony_ci if (screen->ro && (tmpl->bind & PIPE_BIND_SCANOUT)) 519bf215546Sopenharmony_ci should_tile = false; 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_ci /* Cursors are always linear, and the user can request linear as well. 522bf215546Sopenharmony_ci */ 523bf215546Sopenharmony_ci if (tmpl->bind & (PIPE_BIND_LINEAR | PIPE_BIND_CURSOR)) 524bf215546Sopenharmony_ci should_tile = false; 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci /* No shared objects with LT format -- the kernel only has T-format 527bf215546Sopenharmony_ci * metadata. LT objects are small enough it's not worth the trouble to 528bf215546Sopenharmony_ci * give them metadata to tile. 529bf215546Sopenharmony_ci */ 530bf215546Sopenharmony_ci if ((tmpl->bind & (PIPE_BIND_SHARED | PIPE_BIND_SCANOUT)) && 531bf215546Sopenharmony_ci vc4_size_is_lt(prsc->width0, prsc->height0, rsc->cpp)) 532bf215546Sopenharmony_ci should_tile = false; 533bf215546Sopenharmony_ci 534bf215546Sopenharmony_ci /* If we're sharing or scanning out, we need the ioctl present to 535bf215546Sopenharmony_ci * inform the kernel or the other side. 536bf215546Sopenharmony_ci */ 537bf215546Sopenharmony_ci if ((tmpl->bind & (PIPE_BIND_SHARED | 538bf215546Sopenharmony_ci PIPE_BIND_SCANOUT)) && !screen->has_tiling_ioctl) 539bf215546Sopenharmony_ci should_tile = false; 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_ci /* No user-specified modifier; determine our own. */ 542bf215546Sopenharmony_ci if (count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) { 543bf215546Sopenharmony_ci linear_ok = true; 544bf215546Sopenharmony_ci rsc->tiled = should_tile; 545bf215546Sopenharmony_ci } else if (should_tile && 546bf215546Sopenharmony_ci drm_find_modifier(DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED, 547bf215546Sopenharmony_ci modifiers, count)) { 548bf215546Sopenharmony_ci rsc->tiled = true; 549bf215546Sopenharmony_ci } else if (linear_ok) { 550bf215546Sopenharmony_ci rsc->tiled = false; 551bf215546Sopenharmony_ci } else { 552bf215546Sopenharmony_ci fprintf(stderr, "Unsupported modifier requested\n"); 553bf215546Sopenharmony_ci return NULL; 554bf215546Sopenharmony_ci } 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci if (tmpl->target != PIPE_BUFFER) 557bf215546Sopenharmony_ci rsc->vc4_format = get_resource_texture_format(prsc); 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_ci vc4_setup_slices(rsc, "create"); 560bf215546Sopenharmony_ci if (!vc4_resource_bo_alloc(rsc)) 561bf215546Sopenharmony_ci goto fail; 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci if (screen->has_tiling_ioctl) { 564bf215546Sopenharmony_ci uint64_t modifier; 565bf215546Sopenharmony_ci if (rsc->tiled) 566bf215546Sopenharmony_ci modifier = DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED; 567bf215546Sopenharmony_ci else 568bf215546Sopenharmony_ci modifier = DRM_FORMAT_MOD_LINEAR; 569bf215546Sopenharmony_ci struct drm_vc4_set_tiling set_tiling = { 570bf215546Sopenharmony_ci .handle = rsc->bo->handle, 571bf215546Sopenharmony_ci .modifier = modifier, 572bf215546Sopenharmony_ci }; 573bf215546Sopenharmony_ci int ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_SET_TILING, 574bf215546Sopenharmony_ci &set_tiling); 575bf215546Sopenharmony_ci if (ret != 0) 576bf215546Sopenharmony_ci goto fail; 577bf215546Sopenharmony_ci } 578bf215546Sopenharmony_ci 579bf215546Sopenharmony_ci /* Set up the "scanout resource" (the dmabuf export of our buffer to 580bf215546Sopenharmony_ci * the KMS handle) if the buffer might ever have 581bf215546Sopenharmony_ci * resource_get_handle(WINSYS_HANDLE_TYPE_KMS) called on it. 582bf215546Sopenharmony_ci * create_with_modifiers() doesn't give us usage flags, so we have to 583bf215546Sopenharmony_ci * assume that all calls with modifiers are scanout-possible. 584bf215546Sopenharmony_ci */ 585bf215546Sopenharmony_ci if (screen->ro && 586bf215546Sopenharmony_ci ((tmpl->bind & PIPE_BIND_SCANOUT) || 587bf215546Sopenharmony_ci !(count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID))) { 588bf215546Sopenharmony_ci rsc->scanout = 589bf215546Sopenharmony_ci renderonly_scanout_for_resource(prsc, screen->ro, NULL); 590bf215546Sopenharmony_ci if (!rsc->scanout) 591bf215546Sopenharmony_ci goto fail; 592bf215546Sopenharmony_ci } 593bf215546Sopenharmony_ci 594bf215546Sopenharmony_ci vc4_bo_label(screen, rsc->bo, "%sresource %dx%d@%d/%d", 595bf215546Sopenharmony_ci (tmpl->bind & PIPE_BIND_SCANOUT) ? "scanout " : "", 596bf215546Sopenharmony_ci tmpl->width0, tmpl->height0, 597bf215546Sopenharmony_ci rsc->cpp * 8, prsc->last_level); 598bf215546Sopenharmony_ci 599bf215546Sopenharmony_ci return prsc; 600bf215546Sopenharmony_cifail: 601bf215546Sopenharmony_ci vc4_resource_destroy(pscreen, prsc); 602bf215546Sopenharmony_ci return NULL; 603bf215546Sopenharmony_ci} 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_cistruct pipe_resource * 606bf215546Sopenharmony_civc4_resource_create(struct pipe_screen *pscreen, 607bf215546Sopenharmony_ci const struct pipe_resource *tmpl) 608bf215546Sopenharmony_ci{ 609bf215546Sopenharmony_ci const uint64_t mod = DRM_FORMAT_MOD_INVALID; 610bf215546Sopenharmony_ci return vc4_resource_create_with_modifiers(pscreen, tmpl, &mod, 1); 611bf215546Sopenharmony_ci} 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_cistatic struct pipe_resource * 614bf215546Sopenharmony_civc4_resource_from_handle(struct pipe_screen *pscreen, 615bf215546Sopenharmony_ci const struct pipe_resource *tmpl, 616bf215546Sopenharmony_ci struct winsys_handle *whandle, 617bf215546Sopenharmony_ci unsigned usage) 618bf215546Sopenharmony_ci{ 619bf215546Sopenharmony_ci struct vc4_screen *screen = vc4_screen(pscreen); 620bf215546Sopenharmony_ci struct vc4_resource *rsc = vc4_resource_setup(pscreen, tmpl); 621bf215546Sopenharmony_ci struct pipe_resource *prsc = &rsc->base; 622bf215546Sopenharmony_ci struct vc4_resource_slice *slice = &rsc->slices[0]; 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci if (!rsc) 625bf215546Sopenharmony_ci return NULL; 626bf215546Sopenharmony_ci 627bf215546Sopenharmony_ci switch (whandle->type) { 628bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_SHARED: 629bf215546Sopenharmony_ci rsc->bo = vc4_bo_open_name(screen, whandle->handle); 630bf215546Sopenharmony_ci break; 631bf215546Sopenharmony_ci case WINSYS_HANDLE_TYPE_FD: 632bf215546Sopenharmony_ci rsc->bo = vc4_bo_open_dmabuf(screen, whandle->handle); 633bf215546Sopenharmony_ci break; 634bf215546Sopenharmony_ci default: 635bf215546Sopenharmony_ci fprintf(stderr, 636bf215546Sopenharmony_ci "Attempt to import unsupported handle type %d\n", 637bf215546Sopenharmony_ci whandle->type); 638bf215546Sopenharmony_ci } 639bf215546Sopenharmony_ci 640bf215546Sopenharmony_ci if (!rsc->bo) 641bf215546Sopenharmony_ci goto fail; 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_ci struct drm_vc4_get_tiling get_tiling = { 644bf215546Sopenharmony_ci .handle = rsc->bo->handle, 645bf215546Sopenharmony_ci }; 646bf215546Sopenharmony_ci int ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_GET_TILING, &get_tiling); 647bf215546Sopenharmony_ci 648bf215546Sopenharmony_ci if (ret != 0) { 649bf215546Sopenharmony_ci whandle->modifier = DRM_FORMAT_MOD_LINEAR; 650bf215546Sopenharmony_ci } else if (whandle->modifier == DRM_FORMAT_MOD_INVALID) { 651bf215546Sopenharmony_ci whandle->modifier = get_tiling.modifier; 652bf215546Sopenharmony_ci } else if (whandle->modifier != get_tiling.modifier) { 653bf215546Sopenharmony_ci fprintf(stderr, 654bf215546Sopenharmony_ci "Modifier 0x%llx vs. tiling (0x%llx) mismatch\n", 655bf215546Sopenharmony_ci (long long)whandle->modifier, get_tiling.modifier); 656bf215546Sopenharmony_ci goto fail; 657bf215546Sopenharmony_ci } 658bf215546Sopenharmony_ci 659bf215546Sopenharmony_ci switch (whandle->modifier) { 660bf215546Sopenharmony_ci case DRM_FORMAT_MOD_LINEAR: 661bf215546Sopenharmony_ci rsc->tiled = false; 662bf215546Sopenharmony_ci break; 663bf215546Sopenharmony_ci case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: 664bf215546Sopenharmony_ci rsc->tiled = true; 665bf215546Sopenharmony_ci break; 666bf215546Sopenharmony_ci default: 667bf215546Sopenharmony_ci fprintf(stderr, 668bf215546Sopenharmony_ci "Attempt to import unsupported modifier 0x%llx\n", 669bf215546Sopenharmony_ci (long long)whandle->modifier); 670bf215546Sopenharmony_ci goto fail; 671bf215546Sopenharmony_ci } 672bf215546Sopenharmony_ci 673bf215546Sopenharmony_ci rsc->vc4_format = get_resource_texture_format(prsc); 674bf215546Sopenharmony_ci vc4_setup_slices(rsc, "import"); 675bf215546Sopenharmony_ci 676bf215546Sopenharmony_ci if (whandle->offset != 0) { 677bf215546Sopenharmony_ci if (rsc->tiled) { 678bf215546Sopenharmony_ci fprintf(stderr, 679bf215546Sopenharmony_ci "Attempt to import unsupported " 680bf215546Sopenharmony_ci "winsys offset %u\n", 681bf215546Sopenharmony_ci whandle->offset); 682bf215546Sopenharmony_ci goto fail; 683bf215546Sopenharmony_ci } 684bf215546Sopenharmony_ci 685bf215546Sopenharmony_ci rsc->slices[0].offset += whandle->offset; 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci if (rsc->slices[0].offset + rsc->slices[0].size > 688bf215546Sopenharmony_ci rsc->bo->size) { 689bf215546Sopenharmony_ci fprintf(stderr, "Attempt to import " 690bf215546Sopenharmony_ci "with overflowing offset (%d + %d > %d)\n", 691bf215546Sopenharmony_ci whandle->offset, 692bf215546Sopenharmony_ci rsc->slices[0].size, 693bf215546Sopenharmony_ci rsc->bo->size); 694bf215546Sopenharmony_ci goto fail; 695bf215546Sopenharmony_ci } 696bf215546Sopenharmony_ci } 697bf215546Sopenharmony_ci 698bf215546Sopenharmony_ci if (screen->ro) { 699bf215546Sopenharmony_ci /* Make sure that renderonly has a handle to our buffer in the 700bf215546Sopenharmony_ci * display's fd, so that a later renderonly_get_handle() 701bf215546Sopenharmony_ci * returns correct handles or GEM names. 702bf215546Sopenharmony_ci */ 703bf215546Sopenharmony_ci rsc->scanout = 704bf215546Sopenharmony_ci renderonly_create_gpu_import_for_resource(prsc, 705bf215546Sopenharmony_ci screen->ro, 706bf215546Sopenharmony_ci NULL); 707bf215546Sopenharmony_ci } 708bf215546Sopenharmony_ci 709bf215546Sopenharmony_ci if (rsc->tiled && whandle->stride != slice->stride) { 710bf215546Sopenharmony_ci static bool warned = false; 711bf215546Sopenharmony_ci if (!warned) { 712bf215546Sopenharmony_ci warned = true; 713bf215546Sopenharmony_ci fprintf(stderr, 714bf215546Sopenharmony_ci "Attempting to import %dx%d %s with " 715bf215546Sopenharmony_ci "unsupported stride %d instead of %d\n", 716bf215546Sopenharmony_ci prsc->width0, prsc->height0, 717bf215546Sopenharmony_ci util_format_short_name(prsc->format), 718bf215546Sopenharmony_ci whandle->stride, 719bf215546Sopenharmony_ci slice->stride); 720bf215546Sopenharmony_ci } 721bf215546Sopenharmony_ci goto fail; 722bf215546Sopenharmony_ci } else if (!rsc->tiled) { 723bf215546Sopenharmony_ci slice->stride = whandle->stride; 724bf215546Sopenharmony_ci } 725bf215546Sopenharmony_ci 726bf215546Sopenharmony_ci return prsc; 727bf215546Sopenharmony_ci 728bf215546Sopenharmony_cifail: 729bf215546Sopenharmony_ci vc4_resource_destroy(pscreen, prsc); 730bf215546Sopenharmony_ci return NULL; 731bf215546Sopenharmony_ci} 732bf215546Sopenharmony_ci 733bf215546Sopenharmony_cistatic struct pipe_surface * 734bf215546Sopenharmony_civc4_create_surface(struct pipe_context *pctx, 735bf215546Sopenharmony_ci struct pipe_resource *ptex, 736bf215546Sopenharmony_ci const struct pipe_surface *surf_tmpl) 737bf215546Sopenharmony_ci{ 738bf215546Sopenharmony_ci struct vc4_surface *surface = CALLOC_STRUCT(vc4_surface); 739bf215546Sopenharmony_ci struct vc4_resource *rsc = vc4_resource(ptex); 740bf215546Sopenharmony_ci 741bf215546Sopenharmony_ci if (!surface) 742bf215546Sopenharmony_ci return NULL; 743bf215546Sopenharmony_ci 744bf215546Sopenharmony_ci assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_ci struct pipe_surface *psurf = &surface->base; 747bf215546Sopenharmony_ci unsigned level = surf_tmpl->u.tex.level; 748bf215546Sopenharmony_ci 749bf215546Sopenharmony_ci pipe_reference_init(&psurf->reference, 1); 750bf215546Sopenharmony_ci pipe_resource_reference(&psurf->texture, ptex); 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci psurf->context = pctx; 753bf215546Sopenharmony_ci psurf->format = surf_tmpl->format; 754bf215546Sopenharmony_ci psurf->width = u_minify(ptex->width0, level); 755bf215546Sopenharmony_ci psurf->height = u_minify(ptex->height0, level); 756bf215546Sopenharmony_ci psurf->u.tex.level = level; 757bf215546Sopenharmony_ci psurf->u.tex.first_layer = surf_tmpl->u.tex.first_layer; 758bf215546Sopenharmony_ci psurf->u.tex.last_layer = surf_tmpl->u.tex.last_layer; 759bf215546Sopenharmony_ci surface->offset = (rsc->slices[level].offset + 760bf215546Sopenharmony_ci psurf->u.tex.first_layer * rsc->cube_map_stride); 761bf215546Sopenharmony_ci surface->tiling = rsc->slices[level].tiling; 762bf215546Sopenharmony_ci 763bf215546Sopenharmony_ci return &surface->base; 764bf215546Sopenharmony_ci} 765bf215546Sopenharmony_ci 766bf215546Sopenharmony_cistatic void 767bf215546Sopenharmony_civc4_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf) 768bf215546Sopenharmony_ci{ 769bf215546Sopenharmony_ci pipe_resource_reference(&psurf->texture, NULL); 770bf215546Sopenharmony_ci FREE(psurf); 771bf215546Sopenharmony_ci} 772bf215546Sopenharmony_ci 773bf215546Sopenharmony_cistatic void 774bf215546Sopenharmony_civc4_dump_surface_non_msaa(struct pipe_surface *psurf) 775bf215546Sopenharmony_ci{ 776bf215546Sopenharmony_ci struct pipe_resource *prsc = psurf->texture; 777bf215546Sopenharmony_ci struct vc4_resource *rsc = vc4_resource(prsc); 778bf215546Sopenharmony_ci uint32_t *map = vc4_bo_map(rsc->bo); 779bf215546Sopenharmony_ci uint32_t stride = rsc->slices[0].stride / 4; 780bf215546Sopenharmony_ci uint32_t width = psurf->width; 781bf215546Sopenharmony_ci uint32_t height = psurf->height; 782bf215546Sopenharmony_ci uint32_t chunk_w = width / 79; 783bf215546Sopenharmony_ci uint32_t chunk_h = height / 40; 784bf215546Sopenharmony_ci uint32_t found_colors[10] = { 0 }; 785bf215546Sopenharmony_ci uint32_t num_found_colors = 0; 786bf215546Sopenharmony_ci 787bf215546Sopenharmony_ci if (rsc->vc4_format != VC4_TEXTURE_TYPE_RGBA32R) { 788bf215546Sopenharmony_ci fprintf(stderr, "%s: Unsupported format %s\n", 789bf215546Sopenharmony_ci __func__, util_format_short_name(psurf->format)); 790bf215546Sopenharmony_ci return; 791bf215546Sopenharmony_ci } 792bf215546Sopenharmony_ci 793bf215546Sopenharmony_ci for (int by = 0; by < height; by += chunk_h) { 794bf215546Sopenharmony_ci for (int bx = 0; bx < width; bx += chunk_w) { 795bf215546Sopenharmony_ci int all_found_color = -1; /* nothing found */ 796bf215546Sopenharmony_ci 797bf215546Sopenharmony_ci for (int y = by; y < MIN2(height, by + chunk_h); y++) { 798bf215546Sopenharmony_ci for (int x = bx; x < MIN2(width, bx + chunk_w); x++) { 799bf215546Sopenharmony_ci uint32_t pix = map[y * stride + x]; 800bf215546Sopenharmony_ci 801bf215546Sopenharmony_ci int i; 802bf215546Sopenharmony_ci for (i = 0; i < num_found_colors; i++) { 803bf215546Sopenharmony_ci if (pix == found_colors[i]) 804bf215546Sopenharmony_ci break; 805bf215546Sopenharmony_ci } 806bf215546Sopenharmony_ci if (i == num_found_colors && 807bf215546Sopenharmony_ci num_found_colors < 808bf215546Sopenharmony_ci ARRAY_SIZE(found_colors)) { 809bf215546Sopenharmony_ci found_colors[num_found_colors++] = pix; 810bf215546Sopenharmony_ci } 811bf215546Sopenharmony_ci 812bf215546Sopenharmony_ci if (i < num_found_colors) { 813bf215546Sopenharmony_ci if (all_found_color == -1) 814bf215546Sopenharmony_ci all_found_color = i; 815bf215546Sopenharmony_ci else if (i != all_found_color) 816bf215546Sopenharmony_ci all_found_color = ARRAY_SIZE(found_colors); 817bf215546Sopenharmony_ci } 818bf215546Sopenharmony_ci } 819bf215546Sopenharmony_ci } 820bf215546Sopenharmony_ci /* If all pixels for this chunk have a consistent 821bf215546Sopenharmony_ci * value, then print a character for it. Either a 822bf215546Sopenharmony_ci * fixed name (particularly common for piglit tests), 823bf215546Sopenharmony_ci * or a runtime-generated number. 824bf215546Sopenharmony_ci */ 825bf215546Sopenharmony_ci if (all_found_color >= 0 && 826bf215546Sopenharmony_ci all_found_color < ARRAY_SIZE(found_colors)) { 827bf215546Sopenharmony_ci static const struct { 828bf215546Sopenharmony_ci uint32_t val; 829bf215546Sopenharmony_ci const char *c; 830bf215546Sopenharmony_ci } named_colors[] = { 831bf215546Sopenharmony_ci { 0xff000000, "█" }, 832bf215546Sopenharmony_ci { 0x00000000, "█" }, 833bf215546Sopenharmony_ci { 0xffff0000, "r" }, 834bf215546Sopenharmony_ci { 0xff00ff00, "g" }, 835bf215546Sopenharmony_ci { 0xff0000ff, "b" }, 836bf215546Sopenharmony_ci { 0xffffffff, "w" }, 837bf215546Sopenharmony_ci }; 838bf215546Sopenharmony_ci int i; 839bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(named_colors); i++) { 840bf215546Sopenharmony_ci if (named_colors[i].val == 841bf215546Sopenharmony_ci found_colors[all_found_color]) { 842bf215546Sopenharmony_ci fprintf(stderr, "%s", 843bf215546Sopenharmony_ci named_colors[i].c); 844bf215546Sopenharmony_ci break; 845bf215546Sopenharmony_ci } 846bf215546Sopenharmony_ci } 847bf215546Sopenharmony_ci /* For unnamed colors, print a number and the 848bf215546Sopenharmony_ci * numbers will have values printed at the 849bf215546Sopenharmony_ci * end. 850bf215546Sopenharmony_ci */ 851bf215546Sopenharmony_ci if (i == ARRAY_SIZE(named_colors)) { 852bf215546Sopenharmony_ci fprintf(stderr, "%c", 853bf215546Sopenharmony_ci '0' + all_found_color); 854bf215546Sopenharmony_ci } 855bf215546Sopenharmony_ci } else { 856bf215546Sopenharmony_ci /* If there's no consistent color, print this. 857bf215546Sopenharmony_ci */ 858bf215546Sopenharmony_ci fprintf(stderr, "."); 859bf215546Sopenharmony_ci } 860bf215546Sopenharmony_ci } 861bf215546Sopenharmony_ci fprintf(stderr, "\n"); 862bf215546Sopenharmony_ci } 863bf215546Sopenharmony_ci 864bf215546Sopenharmony_ci for (int i = 0; i < num_found_colors; i++) { 865bf215546Sopenharmony_ci fprintf(stderr, "color %d: 0x%08x\n", i, found_colors[i]); 866bf215546Sopenharmony_ci } 867bf215546Sopenharmony_ci} 868bf215546Sopenharmony_ci 869bf215546Sopenharmony_cistatic uint32_t 870bf215546Sopenharmony_civc4_surface_msaa_get_sample(struct pipe_surface *psurf, 871bf215546Sopenharmony_ci uint32_t x, uint32_t y, uint32_t sample) 872bf215546Sopenharmony_ci{ 873bf215546Sopenharmony_ci struct pipe_resource *prsc = psurf->texture; 874bf215546Sopenharmony_ci struct vc4_resource *rsc = vc4_resource(prsc); 875bf215546Sopenharmony_ci uint32_t tile_w = 32, tile_h = 32; 876bf215546Sopenharmony_ci uint32_t tiles_w = DIV_ROUND_UP(psurf->width, 32); 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci uint32_t tile_x = x / tile_w; 879bf215546Sopenharmony_ci uint32_t tile_y = y / tile_h; 880bf215546Sopenharmony_ci uint32_t *tile = (vc4_bo_map(rsc->bo) + 881bf215546Sopenharmony_ci VC4_TILE_BUFFER_SIZE * (tile_y * tiles_w + tile_x)); 882bf215546Sopenharmony_ci uint32_t subtile_x = x % tile_w; 883bf215546Sopenharmony_ci uint32_t subtile_y = y % tile_h; 884bf215546Sopenharmony_ci 885bf215546Sopenharmony_ci uint32_t quad_samples = VC4_MAX_SAMPLES * 4; 886bf215546Sopenharmony_ci uint32_t tile_stride = quad_samples * tile_w / 2; 887bf215546Sopenharmony_ci 888bf215546Sopenharmony_ci return *((uint32_t *)tile + 889bf215546Sopenharmony_ci (subtile_y >> 1) * tile_stride + 890bf215546Sopenharmony_ci (subtile_x >> 1) * quad_samples + 891bf215546Sopenharmony_ci ((subtile_y & 1) << 1) + 892bf215546Sopenharmony_ci (subtile_x & 1) + 893bf215546Sopenharmony_ci sample); 894bf215546Sopenharmony_ci} 895bf215546Sopenharmony_ci 896bf215546Sopenharmony_cistatic void 897bf215546Sopenharmony_civc4_dump_surface_msaa_char(struct pipe_surface *psurf, 898bf215546Sopenharmony_ci uint32_t start_x, uint32_t start_y, 899bf215546Sopenharmony_ci uint32_t w, uint32_t h) 900bf215546Sopenharmony_ci{ 901bf215546Sopenharmony_ci bool all_same_color = true; 902bf215546Sopenharmony_ci uint32_t all_pix = 0; 903bf215546Sopenharmony_ci 904bf215546Sopenharmony_ci for (int y = start_y; y < start_y + h; y++) { 905bf215546Sopenharmony_ci for (int x = start_x; x < start_x + w; x++) { 906bf215546Sopenharmony_ci for (int s = 0; s < VC4_MAX_SAMPLES; s++) { 907bf215546Sopenharmony_ci uint32_t pix = vc4_surface_msaa_get_sample(psurf, 908bf215546Sopenharmony_ci x, y, 909bf215546Sopenharmony_ci s); 910bf215546Sopenharmony_ci if (x == start_x && y == start_y) 911bf215546Sopenharmony_ci all_pix = pix; 912bf215546Sopenharmony_ci else if (all_pix != pix) 913bf215546Sopenharmony_ci all_same_color = false; 914bf215546Sopenharmony_ci } 915bf215546Sopenharmony_ci } 916bf215546Sopenharmony_ci } 917bf215546Sopenharmony_ci if (all_same_color) { 918bf215546Sopenharmony_ci static const struct { 919bf215546Sopenharmony_ci uint32_t val; 920bf215546Sopenharmony_ci const char *c; 921bf215546Sopenharmony_ci } named_colors[] = { 922bf215546Sopenharmony_ci { 0xff000000, "█" }, 923bf215546Sopenharmony_ci { 0x00000000, "█" }, 924bf215546Sopenharmony_ci { 0xffff0000, "r" }, 925bf215546Sopenharmony_ci { 0xff00ff00, "g" }, 926bf215546Sopenharmony_ci { 0xff0000ff, "b" }, 927bf215546Sopenharmony_ci { 0xffffffff, "w" }, 928bf215546Sopenharmony_ci }; 929bf215546Sopenharmony_ci int i; 930bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(named_colors); i++) { 931bf215546Sopenharmony_ci if (named_colors[i].val == all_pix) { 932bf215546Sopenharmony_ci fprintf(stderr, "%s", 933bf215546Sopenharmony_ci named_colors[i].c); 934bf215546Sopenharmony_ci return; 935bf215546Sopenharmony_ci } 936bf215546Sopenharmony_ci } 937bf215546Sopenharmony_ci fprintf(stderr, "x"); 938bf215546Sopenharmony_ci } else { 939bf215546Sopenharmony_ci fprintf(stderr, "."); 940bf215546Sopenharmony_ci } 941bf215546Sopenharmony_ci} 942bf215546Sopenharmony_ci 943bf215546Sopenharmony_cistatic void 944bf215546Sopenharmony_civc4_dump_surface_msaa(struct pipe_surface *psurf) 945bf215546Sopenharmony_ci{ 946bf215546Sopenharmony_ci uint32_t tile_w = 32, tile_h = 32; 947bf215546Sopenharmony_ci uint32_t tiles_w = DIV_ROUND_UP(psurf->width, tile_w); 948bf215546Sopenharmony_ci uint32_t tiles_h = DIV_ROUND_UP(psurf->height, tile_h); 949bf215546Sopenharmony_ci uint32_t char_w = 140, char_h = 60; 950bf215546Sopenharmony_ci uint32_t char_w_per_tile = char_w / tiles_w - 1; 951bf215546Sopenharmony_ci uint32_t char_h_per_tile = char_h / tiles_h - 1; 952bf215546Sopenharmony_ci 953bf215546Sopenharmony_ci fprintf(stderr, "Surface: %dx%d (%dx MSAA)\n", 954bf215546Sopenharmony_ci psurf->width, psurf->height, psurf->texture->nr_samples); 955bf215546Sopenharmony_ci 956bf215546Sopenharmony_ci for (int x = 0; x < (char_w_per_tile + 1) * tiles_w; x++) 957bf215546Sopenharmony_ci fprintf(stderr, "-"); 958bf215546Sopenharmony_ci fprintf(stderr, "\n"); 959bf215546Sopenharmony_ci 960bf215546Sopenharmony_ci for (int ty = 0; ty < psurf->height; ty += tile_h) { 961bf215546Sopenharmony_ci for (int y = 0; y < char_h_per_tile; y++) { 962bf215546Sopenharmony_ci 963bf215546Sopenharmony_ci for (int tx = 0; tx < psurf->width; tx += tile_w) { 964bf215546Sopenharmony_ci for (int x = 0; x < char_w_per_tile; x++) { 965bf215546Sopenharmony_ci uint32_t bx1 = (x * tile_w / 966bf215546Sopenharmony_ci char_w_per_tile); 967bf215546Sopenharmony_ci uint32_t bx2 = ((x + 1) * tile_w / 968bf215546Sopenharmony_ci char_w_per_tile); 969bf215546Sopenharmony_ci uint32_t by1 = (y * tile_h / 970bf215546Sopenharmony_ci char_h_per_tile); 971bf215546Sopenharmony_ci uint32_t by2 = ((y + 1) * tile_h / 972bf215546Sopenharmony_ci char_h_per_tile); 973bf215546Sopenharmony_ci 974bf215546Sopenharmony_ci vc4_dump_surface_msaa_char(psurf, 975bf215546Sopenharmony_ci tx + bx1, 976bf215546Sopenharmony_ci ty + by1, 977bf215546Sopenharmony_ci bx2 - bx1, 978bf215546Sopenharmony_ci by2 - by1); 979bf215546Sopenharmony_ci } 980bf215546Sopenharmony_ci fprintf(stderr, "|"); 981bf215546Sopenharmony_ci } 982bf215546Sopenharmony_ci fprintf(stderr, "\n"); 983bf215546Sopenharmony_ci } 984bf215546Sopenharmony_ci 985bf215546Sopenharmony_ci for (int x = 0; x < (char_w_per_tile + 1) * tiles_w; x++) 986bf215546Sopenharmony_ci fprintf(stderr, "-"); 987bf215546Sopenharmony_ci fprintf(stderr, "\n"); 988bf215546Sopenharmony_ci } 989bf215546Sopenharmony_ci} 990bf215546Sopenharmony_ci 991bf215546Sopenharmony_ci/** Debug routine to dump the contents of an 8888 surface to the console */ 992bf215546Sopenharmony_civoid 993bf215546Sopenharmony_civc4_dump_surface(struct pipe_surface *psurf) 994bf215546Sopenharmony_ci{ 995bf215546Sopenharmony_ci if (!psurf) 996bf215546Sopenharmony_ci return; 997bf215546Sopenharmony_ci 998bf215546Sopenharmony_ci if (psurf->texture->nr_samples > 1) 999bf215546Sopenharmony_ci vc4_dump_surface_msaa(psurf); 1000bf215546Sopenharmony_ci else 1001bf215546Sopenharmony_ci vc4_dump_surface_non_msaa(psurf); 1002bf215546Sopenharmony_ci} 1003bf215546Sopenharmony_ci 1004bf215546Sopenharmony_cistatic void 1005bf215546Sopenharmony_civc4_flush_resource(struct pipe_context *pctx, struct pipe_resource *resource) 1006bf215546Sopenharmony_ci{ 1007bf215546Sopenharmony_ci /* All calls to flush_resource are followed by a flush of the context, 1008bf215546Sopenharmony_ci * so there's nothing to do. 1009bf215546Sopenharmony_ci */ 1010bf215546Sopenharmony_ci} 1011bf215546Sopenharmony_ci 1012bf215546Sopenharmony_civoid 1013bf215546Sopenharmony_civc4_update_shadow_baselevel_texture(struct pipe_context *pctx, 1014bf215546Sopenharmony_ci struct pipe_sampler_view *pview) 1015bf215546Sopenharmony_ci{ 1016bf215546Sopenharmony_ci struct vc4_context *vc4 = vc4_context(pctx); 1017bf215546Sopenharmony_ci struct vc4_sampler_view *view = vc4_sampler_view(pview); 1018bf215546Sopenharmony_ci struct vc4_resource *shadow = vc4_resource(view->texture); 1019bf215546Sopenharmony_ci struct vc4_resource *orig = vc4_resource(pview->texture); 1020bf215546Sopenharmony_ci 1021bf215546Sopenharmony_ci assert(view->texture != pview->texture); 1022bf215546Sopenharmony_ci 1023bf215546Sopenharmony_ci if (shadow->writes == orig->writes && orig->bo->private) 1024bf215546Sopenharmony_ci return; 1025bf215546Sopenharmony_ci 1026bf215546Sopenharmony_ci perf_debug("Updating %dx%d@%d shadow texture due to %s\n", 1027bf215546Sopenharmony_ci orig->base.width0, orig->base.height0, 1028bf215546Sopenharmony_ci pview->u.tex.first_level, 1029bf215546Sopenharmony_ci pview->u.tex.first_level ? "base level" : "raster layout"); 1030bf215546Sopenharmony_ci 1031bf215546Sopenharmony_ci for (int i = 0; i <= shadow->base.last_level; i++) { 1032bf215546Sopenharmony_ci unsigned width = u_minify(shadow->base.width0, i); 1033bf215546Sopenharmony_ci unsigned height = u_minify(shadow->base.height0, i); 1034bf215546Sopenharmony_ci struct pipe_blit_info info = { 1035bf215546Sopenharmony_ci .dst = { 1036bf215546Sopenharmony_ci .resource = &shadow->base, 1037bf215546Sopenharmony_ci .level = i, 1038bf215546Sopenharmony_ci .box = { 1039bf215546Sopenharmony_ci .x = 0, 1040bf215546Sopenharmony_ci .y = 0, 1041bf215546Sopenharmony_ci .z = 0, 1042bf215546Sopenharmony_ci .width = width, 1043bf215546Sopenharmony_ci .height = height, 1044bf215546Sopenharmony_ci .depth = 1, 1045bf215546Sopenharmony_ci }, 1046bf215546Sopenharmony_ci .format = shadow->base.format, 1047bf215546Sopenharmony_ci }, 1048bf215546Sopenharmony_ci .src = { 1049bf215546Sopenharmony_ci .resource = &orig->base, 1050bf215546Sopenharmony_ci .level = pview->u.tex.first_level + i, 1051bf215546Sopenharmony_ci .box = { 1052bf215546Sopenharmony_ci .x = 0, 1053bf215546Sopenharmony_ci .y = 0, 1054bf215546Sopenharmony_ci .z = 0, 1055bf215546Sopenharmony_ci .width = width, 1056bf215546Sopenharmony_ci .height = height, 1057bf215546Sopenharmony_ci .depth = 1, 1058bf215546Sopenharmony_ci }, 1059bf215546Sopenharmony_ci .format = orig->base.format, 1060bf215546Sopenharmony_ci }, 1061bf215546Sopenharmony_ci .mask = ~0, 1062bf215546Sopenharmony_ci }; 1063bf215546Sopenharmony_ci pctx->blit(pctx, &info); 1064bf215546Sopenharmony_ci } 1065bf215546Sopenharmony_ci 1066bf215546Sopenharmony_ci shadow->writes = orig->writes; 1067bf215546Sopenharmony_ci} 1068bf215546Sopenharmony_ci 1069bf215546Sopenharmony_ci/** 1070bf215546Sopenharmony_ci * Converts a 4-byte index buffer to 2 bytes. 1071bf215546Sopenharmony_ci * 1072bf215546Sopenharmony_ci * Since GLES2 only has support for 1 and 2-byte indices, the hardware doesn't 1073bf215546Sopenharmony_ci * include 4-byte index support, and we have to shrink it down. 1074bf215546Sopenharmony_ci * 1075bf215546Sopenharmony_ci * There's no fallback support for when indices end up being larger than 2^16, 1076bf215546Sopenharmony_ci * though it will at least assertion fail. Also, if the original index data 1077bf215546Sopenharmony_ci * was in user memory, it would be nice to not have uploaded it to a VBO 1078bf215546Sopenharmony_ci * before translating. 1079bf215546Sopenharmony_ci */ 1080bf215546Sopenharmony_cistruct pipe_resource * 1081bf215546Sopenharmony_civc4_get_shadow_index_buffer(struct pipe_context *pctx, 1082bf215546Sopenharmony_ci const struct pipe_draw_info *info, 1083bf215546Sopenharmony_ci uint32_t offset, 1084bf215546Sopenharmony_ci uint32_t count, 1085bf215546Sopenharmony_ci uint32_t *shadow_offset) 1086bf215546Sopenharmony_ci{ 1087bf215546Sopenharmony_ci struct vc4_context *vc4 = vc4_context(pctx); 1088bf215546Sopenharmony_ci struct vc4_resource *orig = vc4_resource(info->index.resource); 1089bf215546Sopenharmony_ci perf_debug("Fallback conversion for %d uint indices\n", count); 1090bf215546Sopenharmony_ci 1091bf215546Sopenharmony_ci void *data; 1092bf215546Sopenharmony_ci struct pipe_resource *shadow_rsc = NULL; 1093bf215546Sopenharmony_ci u_upload_alloc(vc4->uploader, 0, count * 2, 4, 1094bf215546Sopenharmony_ci shadow_offset, &shadow_rsc, &data); 1095bf215546Sopenharmony_ci uint16_t *dst = data; 1096bf215546Sopenharmony_ci 1097bf215546Sopenharmony_ci struct pipe_transfer *src_transfer = NULL; 1098bf215546Sopenharmony_ci const uint32_t *src; 1099bf215546Sopenharmony_ci if (info->has_user_indices) { 1100bf215546Sopenharmony_ci src = (uint32_t*)((char*)info->index.user + offset); 1101bf215546Sopenharmony_ci } else { 1102bf215546Sopenharmony_ci src = pipe_buffer_map_range(pctx, &orig->base, 1103bf215546Sopenharmony_ci offset, 1104bf215546Sopenharmony_ci count * 4, 1105bf215546Sopenharmony_ci PIPE_MAP_READ, &src_transfer); 1106bf215546Sopenharmony_ci } 1107bf215546Sopenharmony_ci 1108bf215546Sopenharmony_ci for (int i = 0; i < count; i++) { 1109bf215546Sopenharmony_ci uint32_t src_index = src[i]; 1110bf215546Sopenharmony_ci assert(src_index <= 0xffff); 1111bf215546Sopenharmony_ci dst[i] = src_index; 1112bf215546Sopenharmony_ci } 1113bf215546Sopenharmony_ci 1114bf215546Sopenharmony_ci if (src_transfer) 1115bf215546Sopenharmony_ci pctx->buffer_unmap(pctx, src_transfer); 1116bf215546Sopenharmony_ci 1117bf215546Sopenharmony_ci return shadow_rsc; 1118bf215546Sopenharmony_ci} 1119bf215546Sopenharmony_ci 1120bf215546Sopenharmony_cistatic const struct u_transfer_vtbl transfer_vtbl = { 1121bf215546Sopenharmony_ci .resource_create = vc4_resource_create, 1122bf215546Sopenharmony_ci .resource_destroy = vc4_resource_destroy, 1123bf215546Sopenharmony_ci .transfer_map = vc4_resource_transfer_map, 1124bf215546Sopenharmony_ci .transfer_unmap = vc4_resource_transfer_unmap, 1125bf215546Sopenharmony_ci .transfer_flush_region = u_default_transfer_flush_region, 1126bf215546Sopenharmony_ci}; 1127bf215546Sopenharmony_ci 1128bf215546Sopenharmony_civoid 1129bf215546Sopenharmony_civc4_resource_screen_init(struct pipe_screen *pscreen) 1130bf215546Sopenharmony_ci{ 1131bf215546Sopenharmony_ci struct vc4_screen *screen = vc4_screen(pscreen); 1132bf215546Sopenharmony_ci 1133bf215546Sopenharmony_ci pscreen->resource_create = vc4_resource_create; 1134bf215546Sopenharmony_ci pscreen->resource_create_with_modifiers = 1135bf215546Sopenharmony_ci vc4_resource_create_with_modifiers; 1136bf215546Sopenharmony_ci pscreen->resource_from_handle = vc4_resource_from_handle; 1137bf215546Sopenharmony_ci pscreen->resource_get_handle = vc4_resource_get_handle; 1138bf215546Sopenharmony_ci pscreen->resource_get_param = vc4_resource_get_param; 1139bf215546Sopenharmony_ci pscreen->resource_destroy = vc4_resource_destroy; 1140bf215546Sopenharmony_ci pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl, 1141bf215546Sopenharmony_ci false, false, 1142bf215546Sopenharmony_ci false, true, 1143bf215546Sopenharmony_ci false); 1144bf215546Sopenharmony_ci 1145bf215546Sopenharmony_ci /* Test if the kernel has GET_TILING; it will return -EINVAL if the 1146bf215546Sopenharmony_ci * ioctl does not exist, but -ENOENT if we pass an impossible handle. 1147bf215546Sopenharmony_ci * 0 cannot be a valid GEM object, so use that. 1148bf215546Sopenharmony_ci */ 1149bf215546Sopenharmony_ci struct drm_vc4_get_tiling get_tiling = { 1150bf215546Sopenharmony_ci .handle = 0x0, 1151bf215546Sopenharmony_ci }; 1152bf215546Sopenharmony_ci int ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_GET_TILING, &get_tiling); 1153bf215546Sopenharmony_ci if (ret == -1 && errno == ENOENT) 1154bf215546Sopenharmony_ci screen->has_tiling_ioctl = true; 1155bf215546Sopenharmony_ci} 1156bf215546Sopenharmony_ci 1157bf215546Sopenharmony_civoid 1158bf215546Sopenharmony_civc4_resource_context_init(struct pipe_context *pctx) 1159bf215546Sopenharmony_ci{ 1160bf215546Sopenharmony_ci pctx->buffer_map = u_transfer_helper_transfer_map; 1161bf215546Sopenharmony_ci pctx->texture_map = u_transfer_helper_transfer_map; 1162bf215546Sopenharmony_ci pctx->transfer_flush_region = u_transfer_helper_transfer_flush_region; 1163bf215546Sopenharmony_ci pctx->buffer_unmap = u_transfer_helper_transfer_unmap; 1164bf215546Sopenharmony_ci pctx->texture_unmap = u_transfer_helper_transfer_unmap; 1165bf215546Sopenharmony_ci pctx->buffer_subdata = u_default_buffer_subdata; 1166bf215546Sopenharmony_ci pctx->texture_subdata = vc4_texture_subdata; 1167bf215546Sopenharmony_ci pctx->create_surface = vc4_create_surface; 1168bf215546Sopenharmony_ci pctx->surface_destroy = vc4_surface_destroy; 1169bf215546Sopenharmony_ci pctx->resource_copy_region = util_resource_copy_region; 1170bf215546Sopenharmony_ci pctx->blit = vc4_blit; 1171bf215546Sopenharmony_ci pctx->flush_resource = vc4_flush_resource; 1172bf215546Sopenharmony_ci} 1173