1/* 2 * Copyright (c) 2017-2019 Lima Project 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sub license, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the 12 * next paragraph) shall be included in all copies or substantial portions 13 * of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 */ 24 25#include "util/u_memory.h" 26#include "util/u_blitter.h" 27#include "util/u_upload_mgr.h" 28#include "util/u_math.h" 29#include "util/u_debug.h" 30#include "util/ralloc.h" 31#include "util/u_inlines.h" 32#include "util/u_suballoc.h" 33#include "util/hash_table.h" 34 35#include "lima_screen.h" 36#include "lima_context.h" 37#include "lima_resource.h" 38#include "lima_bo.h" 39#include "lima_submit.h" 40#include "lima_util.h" 41#include "lima_fence.h" 42 43#include <drm-uapi/lima_drm.h> 44#include <xf86drm.h> 45 46int lima_ctx_num_plb = LIMA_CTX_PLB_DEF_NUM; 47 48uint32_t 49lima_ctx_buff_va(struct lima_context *ctx, enum lima_ctx_buff buff, unsigned submit) 50{ 51 struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff; 52 struct lima_resource *res = lima_resource(cbs->res); 53 54 if (submit & LIMA_CTX_BUFF_SUBMIT_GP) 55 lima_submit_add_bo(ctx->gp_submit, res->bo, LIMA_SUBMIT_BO_READ); 56 if (submit & LIMA_CTX_BUFF_SUBMIT_PP) 57 lima_submit_add_bo(ctx->pp_submit, res->bo, LIMA_SUBMIT_BO_READ); 58 59 return res->bo->va + cbs->offset; 60} 61 62void * 63lima_ctx_buff_map(struct lima_context *ctx, enum lima_ctx_buff buff) 64{ 65 struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff; 66 struct lima_resource *res = lima_resource(cbs->res); 67 68 return lima_bo_map(res->bo) + cbs->offset; 69} 70 71void * 72lima_ctx_buff_alloc(struct lima_context *ctx, enum lima_ctx_buff buff, 73 unsigned size, bool uploader) 74{ 75 struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff; 76 void *ret = NULL; 77 78 cbs->size = align(size, 0x40); 79 80 if (uploader) 81 u_upload_alloc(ctx->uploader, 0, cbs->size, 0x40, &cbs->offset, 82 &cbs->res, &ret); 83 else 84 u_suballocator_alloc(ctx->suballocator, cbs->size, 0x10, 85 &cbs->offset, &cbs->res); 86 87 return ret; 88} 89 90static int 91lima_context_create_drm_ctx(struct lima_screen *screen) 92{ 93 struct drm_lima_ctx_create req = {0}; 94 95 int ret = drmIoctl(screen->fd, DRM_IOCTL_LIMA_CTX_CREATE, &req); 96 if (ret) 97 return errno; 98 99 return req.id; 100} 101 102static void 103lima_context_free_drm_ctx(struct lima_screen *screen, int id) 104{ 105 struct drm_lima_ctx_free req = { 106 .id = id, 107 }; 108 109 drmIoctl(screen->fd, DRM_IOCTL_LIMA_CTX_FREE, &req); 110} 111 112static void 113lima_context_destroy(struct pipe_context *pctx) 114{ 115 struct lima_context *ctx = lima_context(pctx); 116 struct lima_screen *screen = lima_screen(pctx->screen); 117 118 if (ctx->pp_submit) 119 lima_submit_free(ctx->pp_submit); 120 if (ctx->gp_submit) 121 lima_submit_free(ctx->gp_submit); 122 123 for (int i = 0; i < lima_ctx_buff_num; i++) 124 pipe_resource_reference(&ctx->buffer_state[i].res, NULL); 125 126 lima_state_fini(ctx); 127 128 if (ctx->blitter) 129 util_blitter_destroy(ctx->blitter); 130 131 if (ctx->suballocator) 132 u_suballocator_destroy(ctx->suballocator); 133 134 if (ctx->uploader) 135 u_upload_destroy(ctx->uploader); 136 137 slab_destroy_child(&ctx->transfer_pool); 138 139 for (int i = 0; i < LIMA_CTX_PLB_MAX_NUM; i++) { 140 if (ctx->plb[i]) 141 lima_bo_free(ctx->plb[i]); 142 if (ctx->gp_tile_heap[i]) 143 lima_bo_free(ctx->gp_tile_heap[i]); 144 } 145 146 if (ctx->plb_gp_stream) 147 lima_bo_free(ctx->plb_gp_stream); 148 149 if (ctx->plb_pp_stream) 150 assert(!_mesa_hash_table_num_entries(ctx->plb_pp_stream)); 151 152 lima_context_free_drm_ctx(screen, ctx->id); 153 154 ralloc_free(ctx); 155} 156 157static uint32_t 158plb_pp_stream_hash(const void *key) 159{ 160 return _mesa_hash_data(key, sizeof(struct lima_ctx_plb_pp_stream_key)); 161} 162 163static bool 164plb_pp_stream_compare(const void *key1, const void *key2) 165{ 166 return memcmp(key1, key2, sizeof(struct lima_ctx_plb_pp_stream_key)) == 0; 167} 168 169struct pipe_context * 170lima_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) 171{ 172 struct lima_screen *screen = lima_screen(pscreen); 173 struct lima_context *ctx; 174 175 ctx = rzalloc(screen, struct lima_context); 176 if (!ctx) 177 return NULL; 178 179 ctx->id = lima_context_create_drm_ctx(screen); 180 if (ctx->id < 0) { 181 ralloc_free(ctx); 182 return NULL; 183 } 184 185 ctx->base.screen = pscreen; 186 ctx->base.destroy = lima_context_destroy; 187 188 lima_resource_context_init(ctx); 189 lima_fence_context_init(ctx); 190 lima_state_init(ctx); 191 lima_draw_init(ctx); 192 lima_program_init(ctx); 193 lima_query_init(ctx); 194 195 slab_create_child(&ctx->transfer_pool, &screen->transfer_pool); 196 197 ctx->blitter = util_blitter_create(&ctx->base); 198 if (!ctx->blitter) 199 goto err_out; 200 201 ctx->uploader = u_upload_create_default(&ctx->base); 202 if (!ctx->uploader) 203 goto err_out; 204 ctx->base.stream_uploader = ctx->uploader; 205 ctx->base.const_uploader = ctx->uploader; 206 207 /* for varying output which need not mmap */ 208 ctx->suballocator = 209 u_suballocator_create(&ctx->base, 1024 * 1024, 0, 210 PIPE_USAGE_STREAM, 0, false); 211 if (!ctx->suballocator) 212 goto err_out; 213 214 util_dynarray_init(&ctx->vs_cmd_array, ctx); 215 util_dynarray_init(&ctx->plbu_cmd_array, ctx); 216 217 if (screen->gpu_type == DRM_LIMA_PARAM_GPU_ID_MALI450) 218 ctx->plb_max_blk = 4096; 219 else 220 ctx->plb_max_blk = 512; 221 ctx->plb_size = ctx->plb_max_blk * LIMA_CTX_PLB_BLK_SIZE; 222 ctx->plb_gp_size = ctx->plb_max_blk * 4; 223 224 for (int i = 0; i < lima_ctx_num_plb; i++) { 225 ctx->plb[i] = lima_bo_create(screen, ctx->plb_size, 0); 226 if (!ctx->plb[i]) 227 goto err_out; 228 ctx->gp_tile_heap[i] = lima_bo_create(screen, gp_tile_heap_size, 0); 229 if (!ctx->gp_tile_heap[i]) 230 goto err_out; 231 } 232 233 unsigned plb_gp_stream_size = 234 align(ctx->plb_gp_size * lima_ctx_num_plb, LIMA_PAGE_SIZE); 235 ctx->plb_gp_stream = 236 lima_bo_create(screen, plb_gp_stream_size, 0); 237 if (!ctx->plb_gp_stream) 238 goto err_out; 239 lima_bo_map(ctx->plb_gp_stream); 240 241 /* plb gp stream is static for any framebuffer */ 242 for (int i = 0; i < lima_ctx_num_plb; i++) { 243 uint32_t *plb_gp_stream = ctx->plb_gp_stream->map + i * ctx->plb_gp_size; 244 for (int j = 0; j < ctx->plb_max_blk; j++) 245 plb_gp_stream[j] = ctx->plb[i]->va + LIMA_CTX_PLB_BLK_SIZE * j; 246 } 247 248 if (screen->gpu_type == DRM_LIMA_PARAM_GPU_ID_MALI400) { 249 ctx->plb_pp_stream = _mesa_hash_table_create( 250 ctx, plb_pp_stream_hash, plb_pp_stream_compare); 251 if (!ctx->plb_pp_stream) 252 goto err_out; 253 } 254 255 ctx->gp_submit = lima_submit_create(ctx, LIMA_PIPE_GP); 256 if (!ctx->gp_submit) 257 goto err_out; 258 259 ctx->pp_submit = lima_submit_create(ctx, LIMA_PIPE_PP); 260 if (!ctx->pp_submit) 261 goto err_out; 262 263 return &ctx->base; 264 265err_out: 266 lima_context_destroy(&ctx->base); 267 return NULL; 268} 269 270bool 271lima_need_flush(struct lima_context *ctx, struct lima_bo *bo, bool write) 272{ 273 return lima_submit_has_bo(ctx->gp_submit, bo, write) || 274 lima_submit_has_bo(ctx->pp_submit, bo, write); 275} 276 277bool 278lima_is_scanout(struct lima_context *ctx) 279{ 280 /* If there is no color buffer, it's an FBO */ 281 if (!ctx->framebuffer.base.nr_cbufs) 282 return false; 283 284 return ctx->framebuffer.base.cbufs[0]->texture->bind & PIPE_BIND_DISPLAY_TARGET || 285 ctx->framebuffer.base.cbufs[0]->texture->bind & PIPE_BIND_SCANOUT || 286 ctx->framebuffer.base.cbufs[0]->texture->bind & PIPE_BIND_SHARED; 287} 288