1b8e80941Smrg/* 2b8e80941Smrg * Copyright (c) 2017-2019 Lima Project 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sub license, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the 12b8e80941Smrg * next paragraph) shall be included in all copies or substantial portions 13b8e80941Smrg * of the Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21b8e80941Smrg * DEALINGS IN THE SOFTWARE. 22b8e80941Smrg * 23b8e80941Smrg */ 24b8e80941Smrg 25b8e80941Smrg#include "util/u_memory.h" 26b8e80941Smrg#include "util/u_blitter.h" 27b8e80941Smrg#include "util/u_format.h" 28b8e80941Smrg#include "util/u_inlines.h" 29b8e80941Smrg#include "util/u_math.h" 30b8e80941Smrg#include "util/u_debug.h" 31b8e80941Smrg#include "util/u_transfer.h" 32b8e80941Smrg#include "util/u_surface.h" 33b8e80941Smrg#include "util/hash_table.h" 34b8e80941Smrg#include "util/u_drm.h" 35b8e80941Smrg#include "renderonly/renderonly.h" 36b8e80941Smrg 37b8e80941Smrg#include "state_tracker/drm_driver.h" 38b8e80941Smrg 39b8e80941Smrg#include "drm-uapi/drm_fourcc.h" 40b8e80941Smrg#include "drm-uapi/lima_drm.h" 41b8e80941Smrg 42b8e80941Smrg#include "lima_screen.h" 43b8e80941Smrg#include "lima_context.h" 44b8e80941Smrg#include "lima_resource.h" 45b8e80941Smrg#include "lima_bo.h" 46b8e80941Smrg#include "lima_util.h" 47b8e80941Smrg#include "lima_tiling.h" 48b8e80941Smrg 49b8e80941Smrgstatic struct pipe_resource * 50b8e80941Smrglima_resource_create_scanout(struct pipe_screen *pscreen, 51b8e80941Smrg const struct pipe_resource *templat, 52b8e80941Smrg unsigned width, unsigned height) 53b8e80941Smrg{ 54b8e80941Smrg struct lima_screen *screen = lima_screen(pscreen); 55b8e80941Smrg struct renderonly_scanout *scanout; 56b8e80941Smrg struct winsys_handle handle; 57b8e80941Smrg struct pipe_resource *pres; 58b8e80941Smrg 59b8e80941Smrg struct pipe_resource scanout_templat = *templat; 60b8e80941Smrg scanout_templat.width0 = width; 61b8e80941Smrg scanout_templat.height0 = height; 62b8e80941Smrg scanout_templat.screen = pscreen; 63b8e80941Smrg 64b8e80941Smrg scanout = renderonly_scanout_for_resource(&scanout_templat, 65b8e80941Smrg screen->ro, &handle); 66b8e80941Smrg if (!scanout) 67b8e80941Smrg return NULL; 68b8e80941Smrg 69b8e80941Smrg assert(handle.type == WINSYS_HANDLE_TYPE_FD); 70b8e80941Smrg pres = pscreen->resource_from_handle(pscreen, templat, &handle, 71b8e80941Smrg PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); 72b8e80941Smrg 73b8e80941Smrg close(handle.handle); 74b8e80941Smrg if (!pres) { 75b8e80941Smrg renderonly_scanout_destroy(scanout, screen->ro); 76b8e80941Smrg return NULL; 77b8e80941Smrg } 78b8e80941Smrg 79b8e80941Smrg struct lima_resource *res = lima_resource(pres); 80b8e80941Smrg res->scanout = scanout; 81b8e80941Smrg 82b8e80941Smrg return pres; 83b8e80941Smrg} 84b8e80941Smrg 85b8e80941Smrgstatic uint32_t 86b8e80941Smrgsetup_miptree(struct lima_resource *res, 87b8e80941Smrg unsigned width0, unsigned height0, 88b8e80941Smrg bool should_align_dimensions) 89b8e80941Smrg{ 90b8e80941Smrg struct pipe_resource *pres = &res->base; 91b8e80941Smrg unsigned level; 92b8e80941Smrg unsigned width = width0; 93b8e80941Smrg unsigned height = height0; 94b8e80941Smrg unsigned depth = pres->depth0; 95b8e80941Smrg uint32_t size = 0; 96b8e80941Smrg 97b8e80941Smrg for (level = 0; level <= pres->last_level; level++) { 98b8e80941Smrg uint32_t actual_level_size; 99b8e80941Smrg uint32_t stride; 100b8e80941Smrg unsigned aligned_width; 101b8e80941Smrg unsigned aligned_height; 102b8e80941Smrg 103b8e80941Smrg if (should_align_dimensions) { 104b8e80941Smrg aligned_width = align(width, 16); 105b8e80941Smrg aligned_height = align(height, 16); 106b8e80941Smrg } else { 107b8e80941Smrg aligned_width = width; 108b8e80941Smrg aligned_height = height; 109b8e80941Smrg } 110b8e80941Smrg 111b8e80941Smrg stride = util_format_get_stride(pres->format, aligned_width); 112b8e80941Smrg actual_level_size = stride * 113b8e80941Smrg util_format_get_nblocksy(pres->format, aligned_height) * 114b8e80941Smrg pres->array_size * depth; 115b8e80941Smrg 116b8e80941Smrg res->levels[level].width = aligned_width; 117b8e80941Smrg res->levels[level].stride = stride; 118b8e80941Smrg res->levels[level].offset = size; 119b8e80941Smrg 120b8e80941Smrg /* The start address of each level <= 10 must be 64-aligned 121b8e80941Smrg * in order to be able to pass the addresses 122b8e80941Smrg * to the hardware. 123b8e80941Smrg * The start addresses of level 11 and level 12 are passed 124b8e80941Smrg * implicitely: they start at an offset of respectively 125b8e80941Smrg * 0x0400 and 0x0800 from the start address of level 10 */ 126b8e80941Smrg if (level < 10) 127b8e80941Smrg size += align(actual_level_size, 64); 128b8e80941Smrg else if (level != pres->last_level) 129b8e80941Smrg size += 0x0400; 130b8e80941Smrg else 131b8e80941Smrg size += actual_level_size; /* Save some memory */ 132b8e80941Smrg 133b8e80941Smrg width = u_minify(width, 1); 134b8e80941Smrg height = u_minify(height, 1); 135b8e80941Smrg depth = u_minify(depth, 1); 136b8e80941Smrg } 137b8e80941Smrg 138b8e80941Smrg return size; 139b8e80941Smrg} 140b8e80941Smrg 141b8e80941Smrgstatic struct pipe_resource * 142b8e80941Smrglima_resource_create_bo(struct pipe_screen *pscreen, 143b8e80941Smrg const struct pipe_resource *templat, 144b8e80941Smrg unsigned width, unsigned height, 145b8e80941Smrg bool should_align_dimensions) 146b8e80941Smrg{ 147b8e80941Smrg struct lima_screen *screen = lima_screen(pscreen); 148b8e80941Smrg struct lima_resource *res; 149b8e80941Smrg struct pipe_resource *pres; 150b8e80941Smrg 151b8e80941Smrg res = CALLOC_STRUCT(lima_resource); 152b8e80941Smrg if (!res) 153b8e80941Smrg return NULL; 154b8e80941Smrg 155b8e80941Smrg res->base = *templat; 156b8e80941Smrg res->base.screen = pscreen; 157b8e80941Smrg pipe_reference_init(&res->base.reference, 1); 158b8e80941Smrg 159b8e80941Smrg pres = &res->base; 160b8e80941Smrg 161b8e80941Smrg uint32_t size = setup_miptree(res, width, height, should_align_dimensions); 162b8e80941Smrg size = align(size, LIMA_PAGE_SIZE); 163b8e80941Smrg 164b8e80941Smrg res->bo = lima_bo_create(screen, size, 0); 165b8e80941Smrg if (!res->bo) { 166b8e80941Smrg FREE(res); 167b8e80941Smrg return NULL; 168b8e80941Smrg } 169b8e80941Smrg 170b8e80941Smrg return pres; 171b8e80941Smrg} 172b8e80941Smrg 173b8e80941Smrgstatic struct pipe_resource * 174b8e80941Smrg_lima_resource_create_with_modifiers(struct pipe_screen *pscreen, 175b8e80941Smrg const struct pipe_resource *templat, 176b8e80941Smrg const uint64_t *modifiers, 177b8e80941Smrg int count) 178b8e80941Smrg{ 179b8e80941Smrg struct lima_screen *screen = lima_screen(pscreen); 180b8e80941Smrg bool should_tile = false; 181b8e80941Smrg unsigned width, height; 182b8e80941Smrg bool should_align_dimensions; 183b8e80941Smrg 184b8e80941Smrg /* VBOs/PBOs are untiled (and 1 height). */ 185b8e80941Smrg if (templat->target == PIPE_BUFFER) 186b8e80941Smrg should_tile = false; 187b8e80941Smrg 188b8e80941Smrg if (templat->bind & (PIPE_BIND_LINEAR | PIPE_BIND_SCANOUT)) 189b8e80941Smrg should_tile = false; 190b8e80941Smrg 191b8e80941Smrg /* if linear buffer is not allowed, alloc fail */ 192b8e80941Smrg if (!should_tile && !drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count)) 193b8e80941Smrg return NULL; 194b8e80941Smrg 195b8e80941Smrg if (should_tile || (templat->bind & PIPE_BIND_RENDER_TARGET) || 196b8e80941Smrg (templat->bind & PIPE_BIND_DEPTH_STENCIL)) { 197b8e80941Smrg should_align_dimensions = true; 198b8e80941Smrg width = align(templat->width0, 16); 199b8e80941Smrg height = align(templat->height0, 16); 200b8e80941Smrg } 201b8e80941Smrg else { 202b8e80941Smrg should_align_dimensions = false; 203b8e80941Smrg width = templat->width0; 204b8e80941Smrg height = templat->height0; 205b8e80941Smrg } 206b8e80941Smrg 207b8e80941Smrg struct pipe_resource *pres; 208b8e80941Smrg if (screen->ro && (templat->bind & PIPE_BIND_SCANOUT)) 209b8e80941Smrg pres = lima_resource_create_scanout(pscreen, templat, width, height); 210b8e80941Smrg else 211b8e80941Smrg pres = lima_resource_create_bo(pscreen, templat, width, height, 212b8e80941Smrg should_align_dimensions); 213b8e80941Smrg 214b8e80941Smrg if (pres) { 215b8e80941Smrg struct lima_resource *res = lima_resource(pres); 216b8e80941Smrg res->tiled = should_tile; 217b8e80941Smrg 218b8e80941Smrg debug_printf("%s: pres=%p width=%u height=%u depth=%u target=%d " 219b8e80941Smrg "bind=%x usage=%d tile=%d last_level=%d\n", __func__, 220b8e80941Smrg pres, pres->width0, pres->height0, pres->depth0, 221b8e80941Smrg pres->target, pres->bind, pres->usage, should_tile, templat->last_level); 222b8e80941Smrg } 223b8e80941Smrg return pres; 224b8e80941Smrg} 225b8e80941Smrg 226b8e80941Smrgstatic struct pipe_resource * 227b8e80941Smrglima_resource_create(struct pipe_screen *pscreen, 228b8e80941Smrg const struct pipe_resource *templat) 229b8e80941Smrg{ 230b8e80941Smrg static const uint64_t modifiers[] = { 231b8e80941Smrg DRM_FORMAT_MOD_LINEAR, 232b8e80941Smrg }; 233b8e80941Smrg return _lima_resource_create_with_modifiers(pscreen, templat, modifiers, ARRAY_SIZE(modifiers)); 234b8e80941Smrg} 235b8e80941Smrg 236b8e80941Smrgstatic struct pipe_resource * 237b8e80941Smrglima_resource_create_with_modifiers(struct pipe_screen *pscreen, 238b8e80941Smrg const struct pipe_resource *templat, 239b8e80941Smrg const uint64_t *modifiers, 240b8e80941Smrg int count) 241b8e80941Smrg{ 242b8e80941Smrg struct pipe_resource tmpl = *templat; 243b8e80941Smrg 244b8e80941Smrg /* gbm_bo_create_with_modifiers & gbm_surface_create_with_modifiers 245b8e80941Smrg * don't have usage parameter, but buffer created by these functions 246b8e80941Smrg * may be used for scanout. So we assume buffer created by this 247b8e80941Smrg * function always enable scanout if linear modifier is permitted. 248b8e80941Smrg */ 249b8e80941Smrg if (drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count)) 250b8e80941Smrg tmpl.bind |= PIPE_BIND_SCANOUT; 251b8e80941Smrg 252b8e80941Smrg return _lima_resource_create_with_modifiers(pscreen, &tmpl, modifiers, count); 253b8e80941Smrg} 254b8e80941Smrg 255b8e80941Smrgstatic void 256b8e80941Smrglima_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *pres) 257b8e80941Smrg{ 258b8e80941Smrg struct lima_screen *screen = lima_screen(pscreen); 259b8e80941Smrg struct lima_resource *res = lima_resource(pres); 260b8e80941Smrg 261b8e80941Smrg if (res->bo) 262b8e80941Smrg lima_bo_free(res->bo); 263b8e80941Smrg 264b8e80941Smrg if (res->scanout) 265b8e80941Smrg renderonly_scanout_destroy(res->scanout, screen->ro); 266b8e80941Smrg 267b8e80941Smrg FREE(res); 268b8e80941Smrg} 269b8e80941Smrg 270b8e80941Smrgstatic struct pipe_resource * 271b8e80941Smrglima_resource_from_handle(struct pipe_screen *pscreen, 272b8e80941Smrg const struct pipe_resource *templat, 273b8e80941Smrg struct winsys_handle *handle, unsigned usage) 274b8e80941Smrg{ 275b8e80941Smrg struct lima_resource *res; 276b8e80941Smrg struct lima_screen *screen = lima_screen(pscreen); 277b8e80941Smrg 278b8e80941Smrg res = CALLOC_STRUCT(lima_resource); 279b8e80941Smrg if (!res) 280b8e80941Smrg return NULL; 281b8e80941Smrg 282b8e80941Smrg struct pipe_resource *pres = &res->base; 283b8e80941Smrg *pres = *templat; 284b8e80941Smrg pres->screen = pscreen; 285b8e80941Smrg pipe_reference_init(&pres->reference, 1); 286b8e80941Smrg res->levels[0].offset = 0; 287b8e80941Smrg res->levels[0].stride = handle->stride; 288b8e80941Smrg 289b8e80941Smrg res->bo = lima_bo_import(screen, handle); 290b8e80941Smrg if (!res->bo) { 291b8e80941Smrg FREE(res); 292b8e80941Smrg return NULL; 293b8e80941Smrg } 294b8e80941Smrg 295b8e80941Smrg /* check alignment for the buffer */ 296b8e80941Smrg if (pres->bind & PIPE_BIND_RENDER_TARGET) { 297b8e80941Smrg unsigned width, height, stride, size; 298b8e80941Smrg 299b8e80941Smrg width = align(pres->width0, 16); 300b8e80941Smrg height = align(pres->height0, 16); 301b8e80941Smrg stride = util_format_get_stride(pres->format, width); 302b8e80941Smrg size = util_format_get_2d_size(pres->format, stride, height); 303b8e80941Smrg 304b8e80941Smrg if (res->levels[0].stride != stride || res->bo->size < size) { 305b8e80941Smrg debug_error("import buffer not properly aligned\n"); 306b8e80941Smrg goto err_out; 307b8e80941Smrg } 308b8e80941Smrg 309b8e80941Smrg res->levels[0].width = width; 310b8e80941Smrg } 311b8e80941Smrg else 312b8e80941Smrg res->levels[0].width = pres->width0; 313b8e80941Smrg 314b8e80941Smrg handle->modifier = DRM_FORMAT_MOD_LINEAR; 315b8e80941Smrg res->tiled = false; 316b8e80941Smrg 317b8e80941Smrg return pres; 318b8e80941Smrg 319b8e80941Smrgerr_out: 320b8e80941Smrg lima_resource_destroy(pscreen, pres); 321b8e80941Smrg return NULL; 322b8e80941Smrg} 323b8e80941Smrg 324b8e80941Smrgstatic boolean 325b8e80941Smrglima_resource_get_handle(struct pipe_screen *pscreen, 326b8e80941Smrg struct pipe_context *pctx, 327b8e80941Smrg struct pipe_resource *pres, 328b8e80941Smrg struct winsys_handle *handle, unsigned usage) 329b8e80941Smrg{ 330b8e80941Smrg struct lima_screen *screen = lima_screen(pscreen); 331b8e80941Smrg struct lima_resource *res = lima_resource(pres); 332b8e80941Smrg 333b8e80941Smrg handle->modifier = DRM_FORMAT_MOD_LINEAR; 334b8e80941Smrg 335b8e80941Smrg if (handle->type == WINSYS_HANDLE_TYPE_KMS && screen->ro && 336b8e80941Smrg renderonly_get_handle(res->scanout, handle)) 337b8e80941Smrg return TRUE; 338b8e80941Smrg 339b8e80941Smrg if (!lima_bo_export(res->bo, handle)) 340b8e80941Smrg return FALSE; 341b8e80941Smrg 342b8e80941Smrg handle->stride = res->levels[0].stride; 343b8e80941Smrg return TRUE; 344b8e80941Smrg} 345b8e80941Smrg 346b8e80941Smrgvoid 347b8e80941Smrglima_resource_screen_init(struct lima_screen *screen) 348b8e80941Smrg{ 349b8e80941Smrg screen->base.resource_create = lima_resource_create; 350b8e80941Smrg screen->base.resource_create_with_modifiers = lima_resource_create_with_modifiers; 351b8e80941Smrg screen->base.resource_from_handle = lima_resource_from_handle; 352b8e80941Smrg screen->base.resource_destroy = lima_resource_destroy; 353b8e80941Smrg screen->base.resource_get_handle = lima_resource_get_handle; 354b8e80941Smrg} 355b8e80941Smrg 356b8e80941Smrgstatic struct pipe_surface * 357b8e80941Smrglima_surface_create(struct pipe_context *pctx, 358b8e80941Smrg struct pipe_resource *pres, 359b8e80941Smrg const struct pipe_surface *surf_tmpl) 360b8e80941Smrg{ 361b8e80941Smrg struct lima_surface *surf = CALLOC_STRUCT(lima_surface); 362b8e80941Smrg 363b8e80941Smrg if (!surf) 364b8e80941Smrg return NULL; 365b8e80941Smrg 366b8e80941Smrg assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); 367b8e80941Smrg 368b8e80941Smrg struct pipe_surface *psurf = &surf->base; 369b8e80941Smrg unsigned level = surf_tmpl->u.tex.level; 370b8e80941Smrg 371b8e80941Smrg pipe_reference_init(&psurf->reference, 1); 372b8e80941Smrg pipe_resource_reference(&psurf->texture, pres); 373b8e80941Smrg 374b8e80941Smrg psurf->context = pctx; 375b8e80941Smrg psurf->format = surf_tmpl->format; 376b8e80941Smrg psurf->width = u_minify(pres->width0, level); 377b8e80941Smrg psurf->height = u_minify(pres->height0, level); 378b8e80941Smrg psurf->u.tex.level = level; 379b8e80941Smrg psurf->u.tex.first_layer = surf_tmpl->u.tex.first_layer; 380b8e80941Smrg psurf->u.tex.last_layer = surf_tmpl->u.tex.last_layer; 381b8e80941Smrg 382b8e80941Smrg surf->tiled_w = align(psurf->width, 16) >> 4; 383b8e80941Smrg surf->tiled_h = align(psurf->height, 16) >> 4; 384b8e80941Smrg 385b8e80941Smrg struct lima_context *ctx = lima_context(pctx); 386b8e80941Smrg if (ctx->plb_pp_stream) { 387b8e80941Smrg struct lima_ctx_plb_pp_stream_key key = { 388b8e80941Smrg .tiled_w = surf->tiled_w, 389b8e80941Smrg .tiled_h = surf->tiled_h, 390b8e80941Smrg }; 391b8e80941Smrg 392b8e80941Smrg for (int i = 0; i < lima_ctx_num_plb; i++) { 393b8e80941Smrg key.plb_index = i; 394b8e80941Smrg 395b8e80941Smrg struct hash_entry *entry = 396b8e80941Smrg _mesa_hash_table_search(ctx->plb_pp_stream, &key); 397b8e80941Smrg if (entry) { 398b8e80941Smrg struct lima_ctx_plb_pp_stream *s = entry->data; 399b8e80941Smrg s->refcnt++; 400b8e80941Smrg } 401b8e80941Smrg else { 402b8e80941Smrg struct lima_ctx_plb_pp_stream *s = 403b8e80941Smrg ralloc(ctx->plb_pp_stream, struct lima_ctx_plb_pp_stream); 404b8e80941Smrg s->key.plb_index = i; 405b8e80941Smrg s->key.tiled_w = surf->tiled_w; 406b8e80941Smrg s->key.tiled_h = surf->tiled_h; 407b8e80941Smrg s->refcnt = 1; 408b8e80941Smrg s->bo = NULL; 409b8e80941Smrg _mesa_hash_table_insert(ctx->plb_pp_stream, &s->key, s); 410b8e80941Smrg } 411b8e80941Smrg } 412b8e80941Smrg } 413b8e80941Smrg 414b8e80941Smrg return &surf->base; 415b8e80941Smrg} 416b8e80941Smrg 417b8e80941Smrgstatic void 418b8e80941Smrglima_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf) 419b8e80941Smrg{ 420b8e80941Smrg struct lima_surface *surf = lima_surface(psurf); 421b8e80941Smrg /* psurf->context may be not equal with pctx (i.e. glxinfo) */ 422b8e80941Smrg struct lima_context *ctx = lima_context(psurf->context); 423b8e80941Smrg 424b8e80941Smrg if (ctx->plb_pp_stream) { 425b8e80941Smrg struct lima_ctx_plb_pp_stream_key key = { 426b8e80941Smrg .tiled_w = surf->tiled_w, 427b8e80941Smrg .tiled_h = surf->tiled_h, 428b8e80941Smrg }; 429b8e80941Smrg 430b8e80941Smrg for (int i = 0; i < lima_ctx_num_plb; i++) { 431b8e80941Smrg key.plb_index = i; 432b8e80941Smrg 433b8e80941Smrg struct hash_entry *entry = 434b8e80941Smrg _mesa_hash_table_search(ctx->plb_pp_stream, &key); 435b8e80941Smrg struct lima_ctx_plb_pp_stream *s = entry->data; 436b8e80941Smrg if (--s->refcnt == 0) { 437b8e80941Smrg if (s->bo) 438b8e80941Smrg lima_bo_free(s->bo); 439b8e80941Smrg _mesa_hash_table_remove(ctx->plb_pp_stream, entry); 440b8e80941Smrg ralloc_free(s); 441b8e80941Smrg } 442b8e80941Smrg } 443b8e80941Smrg } 444b8e80941Smrg 445b8e80941Smrg pipe_resource_reference(&psurf->texture, NULL); 446b8e80941Smrg FREE(surf); 447b8e80941Smrg} 448b8e80941Smrg 449b8e80941Smrgstatic void * 450b8e80941Smrglima_transfer_map(struct pipe_context *pctx, 451b8e80941Smrg struct pipe_resource *pres, 452b8e80941Smrg unsigned level, 453b8e80941Smrg unsigned usage, 454b8e80941Smrg const struct pipe_box *box, 455b8e80941Smrg struct pipe_transfer **pptrans) 456b8e80941Smrg{ 457b8e80941Smrg struct lima_context *ctx = lima_context(pctx); 458b8e80941Smrg struct lima_resource *res = lima_resource(pres); 459b8e80941Smrg struct lima_bo *bo = res->bo; 460b8e80941Smrg struct lima_transfer *trans; 461b8e80941Smrg struct pipe_transfer *ptrans; 462b8e80941Smrg 463b8e80941Smrg /* No direct mappings of tiled, since we need to manually 464b8e80941Smrg * tile/untile. 465b8e80941Smrg */ 466b8e80941Smrg if (res->tiled && (usage & PIPE_TRANSFER_MAP_DIRECTLY)) 467b8e80941Smrg return NULL; 468b8e80941Smrg 469b8e80941Smrg /* use once buffers are made sure to not read/write overlapped 470b8e80941Smrg * range, so no need to sync */ 471b8e80941Smrg if (pres->usage != PIPE_USAGE_STREAM) { 472b8e80941Smrg if (usage & PIPE_TRANSFER_READ_WRITE) { 473b8e80941Smrg if (lima_need_flush(ctx, bo, usage & PIPE_TRANSFER_WRITE)) 474b8e80941Smrg lima_flush(ctx); 475b8e80941Smrg 476b8e80941Smrg unsigned op = usage & PIPE_TRANSFER_WRITE ? 477b8e80941Smrg LIMA_GEM_WAIT_WRITE : LIMA_GEM_WAIT_READ; 478b8e80941Smrg lima_bo_wait(bo, op, PIPE_TIMEOUT_INFINITE); 479b8e80941Smrg } 480b8e80941Smrg } 481b8e80941Smrg 482b8e80941Smrg if (!lima_bo_map(bo)) 483b8e80941Smrg return NULL; 484b8e80941Smrg 485b8e80941Smrg trans = slab_alloc(&ctx->transfer_pool); 486b8e80941Smrg if (!trans) 487b8e80941Smrg return NULL; 488b8e80941Smrg 489b8e80941Smrg memset(trans, 0, sizeof(*trans)); 490b8e80941Smrg ptrans = &trans->base; 491b8e80941Smrg 492b8e80941Smrg pipe_resource_reference(&ptrans->resource, pres); 493b8e80941Smrg ptrans->level = level; 494b8e80941Smrg ptrans->usage = usage; 495b8e80941Smrg ptrans->box = *box; 496b8e80941Smrg 497b8e80941Smrg *pptrans = ptrans; 498b8e80941Smrg 499b8e80941Smrg if (res->tiled) { 500b8e80941Smrg ptrans->stride = util_format_get_stride(pres->format, ptrans->box.width); 501b8e80941Smrg ptrans->layer_stride = ptrans->stride * ptrans->box.height; 502b8e80941Smrg 503b8e80941Smrg trans->staging = malloc(ptrans->stride * ptrans->box.height * ptrans->box.depth); 504b8e80941Smrg 505b8e80941Smrg if (usage & PIPE_TRANSFER_READ) 506b8e80941Smrg lima_load_tiled_image(trans->staging, bo->map + res->levels[level].offset, 507b8e80941Smrg &ptrans->box, 508b8e80941Smrg ptrans->stride, 509b8e80941Smrg res->levels[level].stride, 510b8e80941Smrg util_format_get_blocksize(pres->format)); 511b8e80941Smrg 512b8e80941Smrg return trans->staging; 513b8e80941Smrg } else { 514b8e80941Smrg ptrans->stride = res->levels[level].stride; 515b8e80941Smrg ptrans->layer_stride = ptrans->stride * box->height; 516b8e80941Smrg 517b8e80941Smrg return bo->map + res->levels[level].offset + 518b8e80941Smrg box->z * ptrans->layer_stride + 519b8e80941Smrg box->y / util_format_get_blockheight(pres->format) * ptrans->stride + 520b8e80941Smrg box->x / util_format_get_blockwidth(pres->format) * 521b8e80941Smrg util_format_get_blocksize(pres->format); 522b8e80941Smrg } 523b8e80941Smrg} 524b8e80941Smrg 525b8e80941Smrgstatic void 526b8e80941Smrglima_transfer_flush_region(struct pipe_context *pctx, 527b8e80941Smrg struct pipe_transfer *ptrans, 528b8e80941Smrg const struct pipe_box *box) 529b8e80941Smrg{ 530b8e80941Smrg 531b8e80941Smrg} 532b8e80941Smrg 533b8e80941Smrgstatic void 534b8e80941Smrglima_transfer_unmap(struct pipe_context *pctx, 535b8e80941Smrg struct pipe_transfer *ptrans) 536b8e80941Smrg{ 537b8e80941Smrg struct lima_context *ctx = lima_context(pctx); 538b8e80941Smrg struct lima_transfer *trans = lima_transfer(ptrans); 539b8e80941Smrg struct lima_resource *res = lima_resource(ptrans->resource); 540b8e80941Smrg struct lima_bo *bo = res->bo; 541b8e80941Smrg struct pipe_resource *pres; 542b8e80941Smrg 543b8e80941Smrg if (trans->staging) { 544b8e80941Smrg pres = &res->base; 545b8e80941Smrg if (ptrans->usage & PIPE_TRANSFER_WRITE) 546b8e80941Smrg lima_store_tiled_image(bo->map + res->levels[ptrans->level].offset, trans->staging, 547b8e80941Smrg &ptrans->box, 548b8e80941Smrg res->levels[ptrans->level].stride, 549b8e80941Smrg ptrans->stride, 550b8e80941Smrg util_format_get_blocksize(pres->format)); 551b8e80941Smrg free(trans->staging); 552b8e80941Smrg } 553b8e80941Smrg 554b8e80941Smrg pipe_resource_reference(&ptrans->resource, NULL); 555b8e80941Smrg slab_free(&ctx->transfer_pool, trans); 556b8e80941Smrg} 557b8e80941Smrg 558b8e80941Smrgstatic void 559b8e80941Smrglima_util_blitter_save_states(struct lima_context *ctx) 560b8e80941Smrg{ 561b8e80941Smrg util_blitter_save_blend(ctx->blitter, (void *)ctx->blend); 562b8e80941Smrg util_blitter_save_depth_stencil_alpha(ctx->blitter, (void *)ctx->zsa); 563b8e80941Smrg util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref); 564b8e80941Smrg util_blitter_save_rasterizer(ctx->blitter, (void *)ctx->rasterizer); 565b8e80941Smrg util_blitter_save_fragment_shader(ctx->blitter, ctx->fs); 566b8e80941Smrg util_blitter_save_vertex_shader(ctx->blitter, ctx->vs); 567b8e80941Smrg util_blitter_save_viewport(ctx->blitter, 568b8e80941Smrg &ctx->viewport.transform); 569b8e80941Smrg util_blitter_save_scissor(ctx->blitter, &ctx->scissor); 570b8e80941Smrg util_blitter_save_vertex_elements(ctx->blitter, 571b8e80941Smrg ctx->vertex_elements); 572b8e80941Smrg util_blitter_save_vertex_buffer_slot(ctx->blitter, 573b8e80941Smrg ctx->vertex_buffers.vb); 574b8e80941Smrg 575b8e80941Smrg util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer.base); 576b8e80941Smrg 577b8e80941Smrg util_blitter_save_fragment_sampler_states(ctx->blitter, 578b8e80941Smrg ctx->tex_stateobj.num_samplers, 579b8e80941Smrg (void**)ctx->tex_stateobj.samplers); 580b8e80941Smrg util_blitter_save_fragment_sampler_views(ctx->blitter, 581b8e80941Smrg ctx->tex_stateobj.num_textures, 582b8e80941Smrg ctx->tex_stateobj.textures); 583b8e80941Smrg} 584b8e80941Smrg 585b8e80941Smrgstatic void 586b8e80941Smrglima_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) 587b8e80941Smrg{ 588b8e80941Smrg struct lima_context *ctx = lima_context(pctx); 589b8e80941Smrg struct pipe_blit_info info = *blit_info; 590b8e80941Smrg 591b8e80941Smrg if (util_try_blit_via_copy_region(pctx, &info)) { 592b8e80941Smrg return; /* done */ 593b8e80941Smrg } 594b8e80941Smrg 595b8e80941Smrg if (info.mask & PIPE_MASK_S) { 596b8e80941Smrg debug_printf("lima: cannot blit stencil, skipping\n"); 597b8e80941Smrg info.mask &= ~PIPE_MASK_S; 598b8e80941Smrg } 599b8e80941Smrg 600b8e80941Smrg if (!util_blitter_is_blit_supported(ctx->blitter, &info)) { 601b8e80941Smrg debug_printf("lima: blit unsupported %s -> %s\n", 602b8e80941Smrg util_format_short_name(info.src.resource->format), 603b8e80941Smrg util_format_short_name(info.dst.resource->format)); 604b8e80941Smrg return; 605b8e80941Smrg } 606b8e80941Smrg 607b8e80941Smrg lima_util_blitter_save_states(ctx); 608b8e80941Smrg 609b8e80941Smrg util_blitter_blit(ctx->blitter, &info); 610b8e80941Smrg} 611b8e80941Smrg 612b8e80941Smrgstatic void 613b8e80941Smrglima_flush_resource(struct pipe_context *pctx, struct pipe_resource *resource) 614b8e80941Smrg{ 615b8e80941Smrg 616b8e80941Smrg} 617b8e80941Smrg 618b8e80941Smrgvoid 619b8e80941Smrglima_resource_context_init(struct lima_context *ctx) 620b8e80941Smrg{ 621b8e80941Smrg ctx->base.create_surface = lima_surface_create; 622b8e80941Smrg ctx->base.surface_destroy = lima_surface_destroy; 623b8e80941Smrg 624b8e80941Smrg /* TODO: optimize these functions to read/write data directly 625b8e80941Smrg * from/to target instead of creating a staging memory for tiled 626b8e80941Smrg * buffer indirectly 627b8e80941Smrg */ 628b8e80941Smrg ctx->base.buffer_subdata = u_default_buffer_subdata; 629b8e80941Smrg ctx->base.texture_subdata = u_default_texture_subdata; 630b8e80941Smrg ctx->base.resource_copy_region = util_resource_copy_region; 631b8e80941Smrg 632b8e80941Smrg ctx->base.blit = lima_blit; 633b8e80941Smrg 634b8e80941Smrg ctx->base.transfer_map = lima_transfer_map; 635b8e80941Smrg ctx->base.transfer_flush_region = lima_transfer_flush_region; 636b8e80941Smrg ctx->base.transfer_unmap = lima_transfer_unmap; 637b8e80941Smrg 638b8e80941Smrg ctx->base.flush_resource = lima_flush_resource; 639b8e80941Smrg} 640