19f464c52Smaya/*
29f464c52Smaya * Copyright (c) 2017-2019 Lima Project
39f464c52Smaya *
49f464c52Smaya * Permission is hereby granted, free of charge, to any person obtaining a
59f464c52Smaya * copy of this software and associated documentation files (the "Software"),
69f464c52Smaya * to deal in the Software without restriction, including without limitation
79f464c52Smaya * the rights to use, copy, modify, merge, publish, distribute, sub license,
89f464c52Smaya * and/or sell copies of the Software, and to permit persons to whom the
99f464c52Smaya * Software is furnished to do so, subject to the following conditions:
109f464c52Smaya *
119f464c52Smaya * The above copyright notice and this permission notice (including the
129f464c52Smaya * next paragraph) shall be included in all copies or substantial portions
139f464c52Smaya * of the Software.
149f464c52Smaya *
159f464c52Smaya * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
169f464c52Smaya * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
179f464c52Smaya * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
189f464c52Smaya * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
199f464c52Smaya * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
209f464c52Smaya * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
219f464c52Smaya * DEALINGS IN THE SOFTWARE.
229f464c52Smaya *
239f464c52Smaya */
249f464c52Smaya
259f464c52Smaya#include "util/u_memory.h"
269f464c52Smaya#include "util/u_blitter.h"
279f464c52Smaya#include "util/u_upload_mgr.h"
289f464c52Smaya#include "util/u_math.h"
299f464c52Smaya#include "util/u_debug.h"
309f464c52Smaya#include "util/ralloc.h"
319f464c52Smaya#include "util/u_inlines.h"
329f464c52Smaya#include "util/hash_table.h"
339f464c52Smaya
349f464c52Smaya#include "lima_screen.h"
359f464c52Smaya#include "lima_context.h"
369f464c52Smaya#include "lima_resource.h"
379f464c52Smaya#include "lima_bo.h"
387ec681f3Smrg#include "lima_job.h"
399f464c52Smaya#include "lima_util.h"
409f464c52Smaya#include "lima_fence.h"
419f464c52Smaya
429f464c52Smaya#include <drm-uapi/lima_drm.h>
439f464c52Smaya#include <xf86drm.h>
449f464c52Smaya
459f464c52Smayaint lima_ctx_num_plb = LIMA_CTX_PLB_DEF_NUM;
469f464c52Smaya
479f464c52Smayauint32_t
487ec681f3Smrglima_ctx_buff_va(struct lima_context *ctx, enum lima_ctx_buff buff)
499f464c52Smaya{
507ec681f3Smrg   struct lima_job *job = lima_job_get(ctx);
519f464c52Smaya   struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
529f464c52Smaya   struct lima_resource *res = lima_resource(cbs->res);
537ec681f3Smrg   int pipe = buff < lima_ctx_buff_num_gp ? LIMA_PIPE_GP : LIMA_PIPE_PP;
549f464c52Smaya
557ec681f3Smrg   lima_job_add_bo(job, pipe, res->bo, LIMA_SUBMIT_BO_READ);
569f464c52Smaya
579f464c52Smaya   return res->bo->va + cbs->offset;
589f464c52Smaya}
599f464c52Smaya
609f464c52Smayavoid *
619f464c52Smayalima_ctx_buff_map(struct lima_context *ctx, enum lima_ctx_buff buff)
629f464c52Smaya{
639f464c52Smaya   struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
649f464c52Smaya   struct lima_resource *res = lima_resource(cbs->res);
659f464c52Smaya
669f464c52Smaya   return lima_bo_map(res->bo) + cbs->offset;
679f464c52Smaya}
689f464c52Smaya
699f464c52Smayavoid *
709f464c52Smayalima_ctx_buff_alloc(struct lima_context *ctx, enum lima_ctx_buff buff,
717ec681f3Smrg                    unsigned size)
729f464c52Smaya{
739f464c52Smaya   struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
749f464c52Smaya   void *ret = NULL;
759f464c52Smaya
769f464c52Smaya   cbs->size = align(size, 0x40);
779f464c52Smaya
787ec681f3Smrg   u_upload_alloc(ctx->uploader, 0, cbs->size, 0x40, &cbs->offset,
797ec681f3Smrg                  &cbs->res, &ret);
809f464c52Smaya
819f464c52Smaya   return ret;
829f464c52Smaya}
839f464c52Smaya
849f464c52Smayastatic int
859f464c52Smayalima_context_create_drm_ctx(struct lima_screen *screen)
869f464c52Smaya{
879f464c52Smaya   struct drm_lima_ctx_create req = {0};
889f464c52Smaya
899f464c52Smaya   int ret = drmIoctl(screen->fd, DRM_IOCTL_LIMA_CTX_CREATE, &req);
909f464c52Smaya   if (ret)
919f464c52Smaya      return errno;
929f464c52Smaya
939f464c52Smaya   return req.id;
949f464c52Smaya}
959f464c52Smaya
969f464c52Smayastatic void
979f464c52Smayalima_context_free_drm_ctx(struct lima_screen *screen, int id)
989f464c52Smaya{
999f464c52Smaya   struct drm_lima_ctx_free req = {
1009f464c52Smaya      .id = id,
1019f464c52Smaya   };
1029f464c52Smaya
1039f464c52Smaya   drmIoctl(screen->fd, DRM_IOCTL_LIMA_CTX_FREE, &req);
1049f464c52Smaya}
1059f464c52Smaya
1067ec681f3Smrgstatic void
1077ec681f3Smrglima_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
1087ec681f3Smrg{
1097ec681f3Smrg   struct lima_context *ctx = lima_context(pctx);
1107ec681f3Smrg
1117ec681f3Smrg   struct hash_entry *entry = _mesa_hash_table_search(ctx->write_jobs, prsc);
1127ec681f3Smrg   if (!entry)
1137ec681f3Smrg      return;
1147ec681f3Smrg
1157ec681f3Smrg   struct lima_job *job = entry->data;
1167ec681f3Smrg   if (job->key.zsbuf && (job->key.zsbuf->texture == prsc))
1177ec681f3Smrg      job->resolve &= ~(PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL);
1187ec681f3Smrg
1197ec681f3Smrg   if (job->key.cbuf && (job->key.cbuf->texture == prsc))
1207ec681f3Smrg      job->resolve &= ~PIPE_CLEAR_COLOR0;
1217ec681f3Smrg
1227ec681f3Smrg   _mesa_hash_table_remove_key(ctx->write_jobs, prsc);
1237ec681f3Smrg}
1247ec681f3Smrg
1257ec681f3Smrgstatic void
1267ec681f3Smrgplb_pp_stream_delete_fn(struct hash_entry *entry)
1277ec681f3Smrg{
1287ec681f3Smrg   struct lima_ctx_plb_pp_stream *s = entry->data;
1297ec681f3Smrg
1307ec681f3Smrg   lima_bo_unreference(s->bo);
1317ec681f3Smrg   list_del(&s->lru_list);
1327ec681f3Smrg   ralloc_free(s);
1337ec681f3Smrg}
1347ec681f3Smrg
1359f464c52Smayastatic void
1369f464c52Smayalima_context_destroy(struct pipe_context *pctx)
1379f464c52Smaya{
1389f464c52Smaya   struct lima_context *ctx = lima_context(pctx);
1399f464c52Smaya   struct lima_screen *screen = lima_screen(pctx->screen);
1409f464c52Smaya
1417ec681f3Smrg   lima_job_fini(ctx);
1429f464c52Smaya
1439f464c52Smaya   for (int i = 0; i < lima_ctx_buff_num; i++)
1449f464c52Smaya      pipe_resource_reference(&ctx->buffer_state[i].res, NULL);
1459f464c52Smaya
1467ec681f3Smrg   lima_program_fini(ctx);
1479f464c52Smaya   lima_state_fini(ctx);
1489f464c52Smaya
1499f464c52Smaya   if (ctx->blitter)
1509f464c52Smaya      util_blitter_destroy(ctx->blitter);
1519f464c52Smaya
1529f464c52Smaya   if (ctx->uploader)
1539f464c52Smaya      u_upload_destroy(ctx->uploader);
1549f464c52Smaya
1559f464c52Smaya   slab_destroy_child(&ctx->transfer_pool);
1569f464c52Smaya
1579f464c52Smaya   for (int i = 0; i < LIMA_CTX_PLB_MAX_NUM; i++) {
1589f464c52Smaya      if (ctx->plb[i])
1597ec681f3Smrg         lima_bo_unreference(ctx->plb[i]);
1609f464c52Smaya      if (ctx->gp_tile_heap[i])
1617ec681f3Smrg         lima_bo_unreference(ctx->gp_tile_heap[i]);
1629f464c52Smaya   }
1639f464c52Smaya
1649f464c52Smaya   if (ctx->plb_gp_stream)
1657ec681f3Smrg      lima_bo_unreference(ctx->plb_gp_stream);
1667ec681f3Smrg
1677ec681f3Smrg   if (ctx->gp_output)
1687ec681f3Smrg      lima_bo_unreference(ctx->gp_output);
1699f464c52Smaya
1707ec681f3Smrg   _mesa_hash_table_destroy(ctx->plb_pp_stream,
1717ec681f3Smrg                            plb_pp_stream_delete_fn);
1729f464c52Smaya
1739f464c52Smaya   lima_context_free_drm_ctx(screen, ctx->id);
1749f464c52Smaya
1759f464c52Smaya   ralloc_free(ctx);
1769f464c52Smaya}
1779f464c52Smaya
1789f464c52Smayastatic uint32_t
1799f464c52Smayaplb_pp_stream_hash(const void *key)
1809f464c52Smaya{
1819f464c52Smaya   return _mesa_hash_data(key, sizeof(struct lima_ctx_plb_pp_stream_key));
1829f464c52Smaya}
1839f464c52Smaya
1849f464c52Smayastatic bool
1859f464c52Smayaplb_pp_stream_compare(const void *key1, const void *key2)
1869f464c52Smaya{
1879f464c52Smaya   return memcmp(key1, key2, sizeof(struct lima_ctx_plb_pp_stream_key)) == 0;
1889f464c52Smaya}
1899f464c52Smaya
1907ec681f3Smrgstatic void
1917ec681f3Smrglima_set_debug_callback(struct pipe_context *pctx,
1927ec681f3Smrg                        const struct pipe_debug_callback *cb)
1937ec681f3Smrg{
1947ec681f3Smrg   struct lima_context *ctx = lima_context(pctx);
1957ec681f3Smrg
1967ec681f3Smrg   if (cb)
1977ec681f3Smrg      ctx->debug = *cb;
1987ec681f3Smrg   else
1997ec681f3Smrg      memset(&ctx->debug, 0, sizeof(ctx->debug));
2007ec681f3Smrg}
2017ec681f3Smrg
2029f464c52Smayastruct pipe_context *
2039f464c52Smayalima_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
2049f464c52Smaya{
2059f464c52Smaya   struct lima_screen *screen = lima_screen(pscreen);
2069f464c52Smaya   struct lima_context *ctx;
2079f464c52Smaya
2089f464c52Smaya   ctx = rzalloc(screen, struct lima_context);
2099f464c52Smaya   if (!ctx)
2109f464c52Smaya      return NULL;
2119f464c52Smaya
2129f464c52Smaya   ctx->id = lima_context_create_drm_ctx(screen);
2139f464c52Smaya   if (ctx->id < 0) {
2149f464c52Smaya      ralloc_free(ctx);
2159f464c52Smaya      return NULL;
2169f464c52Smaya   }
2179f464c52Smaya
2189f464c52Smaya   ctx->base.screen = pscreen;
2199f464c52Smaya   ctx->base.destroy = lima_context_destroy;
2207ec681f3Smrg   ctx->base.set_debug_callback = lima_set_debug_callback;
2217ec681f3Smrg   ctx->base.invalidate_resource = lima_invalidate_resource;
2229f464c52Smaya
2239f464c52Smaya   lima_resource_context_init(ctx);
2249f464c52Smaya   lima_fence_context_init(ctx);
2259f464c52Smaya   lima_state_init(ctx);
2269f464c52Smaya   lima_draw_init(ctx);
2279f464c52Smaya   lima_program_init(ctx);
2289f464c52Smaya   lima_query_init(ctx);
2299f464c52Smaya
2309f464c52Smaya   slab_create_child(&ctx->transfer_pool, &screen->transfer_pool);
2319f464c52Smaya
2329f464c52Smaya   ctx->blitter = util_blitter_create(&ctx->base);
2339f464c52Smaya   if (!ctx->blitter)
2349f464c52Smaya      goto err_out;
2359f464c52Smaya
2369f464c52Smaya   ctx->uploader = u_upload_create_default(&ctx->base);
2379f464c52Smaya   if (!ctx->uploader)
2389f464c52Smaya      goto err_out;
2399f464c52Smaya   ctx->base.stream_uploader = ctx->uploader;
2409f464c52Smaya   ctx->base.const_uploader = ctx->uploader;
2419f464c52Smaya
2427ec681f3Smrg   ctx->plb_size = screen->plb_max_blk * LIMA_CTX_PLB_BLK_SIZE;
2437ec681f3Smrg   ctx->plb_gp_size = screen->plb_max_blk * 4;
2447ec681f3Smrg
2457ec681f3Smrg   uint32_t heap_flags;
2467ec681f3Smrg   if (screen->has_growable_heap_buffer) {
2477ec681f3Smrg      /* growable size buffer, initially will allocate 32K (by default)
2487ec681f3Smrg       * backup memory in kernel driver, and will allocate more when GP
2497ec681f3Smrg       * get out of memory interrupt. Max to 16M set here.
2507ec681f3Smrg       */
2517ec681f3Smrg      ctx->gp_tile_heap_size = 0x1000000;
2527ec681f3Smrg      heap_flags = LIMA_BO_FLAG_HEAP;
2537ec681f3Smrg   } else {
2547ec681f3Smrg      /* fix size buffer */
2557ec681f3Smrg      ctx->gp_tile_heap_size = 0x100000;
2567ec681f3Smrg      heap_flags = 0;
2577ec681f3Smrg   }
2589f464c52Smaya
2599f464c52Smaya   for (int i = 0; i < lima_ctx_num_plb; i++) {
2609f464c52Smaya      ctx->plb[i] = lima_bo_create(screen, ctx->plb_size, 0);
2619f464c52Smaya      if (!ctx->plb[i])
2629f464c52Smaya         goto err_out;
2637ec681f3Smrg      ctx->gp_tile_heap[i] = lima_bo_create(screen, ctx->gp_tile_heap_size, heap_flags);
2649f464c52Smaya      if (!ctx->gp_tile_heap[i])
2659f464c52Smaya         goto err_out;
2669f464c52Smaya   }
2679f464c52Smaya
2689f464c52Smaya   unsigned plb_gp_stream_size =
2699f464c52Smaya      align(ctx->plb_gp_size * lima_ctx_num_plb, LIMA_PAGE_SIZE);
2709f464c52Smaya   ctx->plb_gp_stream =
2719f464c52Smaya      lima_bo_create(screen, plb_gp_stream_size, 0);
2729f464c52Smaya   if (!ctx->plb_gp_stream)
2739f464c52Smaya      goto err_out;
2749f464c52Smaya   lima_bo_map(ctx->plb_gp_stream);
2759f464c52Smaya
2769f464c52Smaya   /* plb gp stream is static for any framebuffer */
2779f464c52Smaya   for (int i = 0; i < lima_ctx_num_plb; i++) {
2789f464c52Smaya      uint32_t *plb_gp_stream = ctx->plb_gp_stream->map + i * ctx->plb_gp_size;
2797ec681f3Smrg      for (int j = 0; j < screen->plb_max_blk; j++)
2809f464c52Smaya         plb_gp_stream[j] = ctx->plb[i]->va + LIMA_CTX_PLB_BLK_SIZE * j;
2819f464c52Smaya   }
2829f464c52Smaya
2837ec681f3Smrg   list_inithead(&ctx->plb_pp_stream_lru_list);
2847ec681f3Smrg   ctx->plb_pp_stream = _mesa_hash_table_create(
2857ec681f3Smrg      ctx, plb_pp_stream_hash, plb_pp_stream_compare);
2867ec681f3Smrg   if (!ctx->plb_pp_stream)
2879f464c52Smaya      goto err_out;
2889f464c52Smaya
2897ec681f3Smrg   if (!lima_job_init(ctx))
2909f464c52Smaya      goto err_out;
2919f464c52Smaya
2929f464c52Smaya   return &ctx->base;
2939f464c52Smaya
2949f464c52Smayaerr_out:
2959f464c52Smaya   lima_context_destroy(&ctx->base);
2969f464c52Smaya   return NULL;
2979f464c52Smaya}
298