xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/lima/lima_context.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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_debug_cb.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_job.h"
40 #include "lima_util.h"
41 #include "lima_fence.h"
42 
43 #include <drm-uapi/lima_drm.h>
44 #include <xf86drm.h>
45 
46 int lima_ctx_num_plb = LIMA_CTX_PLB_DEF_NUM;
47 
48 uint32_t
lima_ctx_buff_va(struct lima_context * ctx,enum lima_ctx_buff buff)49 lima_ctx_buff_va(struct lima_context *ctx, enum lima_ctx_buff buff)
50 {
51    struct lima_job *job = lima_job_get(ctx);
52    struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
53    struct lima_resource *res = lima_resource(cbs->res);
54    int pipe = buff < lima_ctx_buff_num_gp ? LIMA_PIPE_GP : LIMA_PIPE_PP;
55 
56    lima_job_add_bo(job, pipe, res->bo, LIMA_SUBMIT_BO_READ);
57 
58    return res->bo->va + cbs->offset;
59 }
60 
61 void *
lima_ctx_buff_map(struct lima_context * ctx,enum lima_ctx_buff buff)62 lima_ctx_buff_map(struct lima_context *ctx, enum lima_ctx_buff buff)
63 {
64    struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
65    struct lima_resource *res = lima_resource(cbs->res);
66 
67    return lima_bo_map(res->bo) + cbs->offset;
68 }
69 
70 void *
lima_ctx_buff_alloc(struct lima_context * ctx,enum lima_ctx_buff buff,unsigned size)71 lima_ctx_buff_alloc(struct lima_context *ctx, enum lima_ctx_buff buff,
72                     unsigned size)
73 {
74    struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
75    void *ret = NULL;
76 
77    cbs->size = align(size, 0x40);
78 
79    u_upload_alloc(ctx->uploader, 0, cbs->size, 0x40, &cbs->offset,
80                   &cbs->res, &ret);
81 
82    return ret;
83 }
84 
85 static int
lima_context_create_drm_ctx(struct lima_screen * screen)86 lima_context_create_drm_ctx(struct lima_screen *screen)
87 {
88    struct drm_lima_ctx_create req = {0};
89 
90    int ret = drmIoctl(screen->fd, DRM_IOCTL_LIMA_CTX_CREATE, &req);
91    if (ret)
92       return errno;
93 
94    return req.id;
95 }
96 
97 static void
lima_context_free_drm_ctx(struct lima_screen * screen,int id)98 lima_context_free_drm_ctx(struct lima_screen *screen, int id)
99 {
100    struct drm_lima_ctx_free req = {
101       .id = id,
102    };
103 
104    drmIoctl(screen->fd, DRM_IOCTL_LIMA_CTX_FREE, &req);
105 }
106 
107 static void
lima_invalidate_resource(struct pipe_context * pctx,struct pipe_resource * prsc)108 lima_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
109 {
110    struct lima_context *ctx = lima_context(pctx);
111 
112    struct hash_entry *entry = _mesa_hash_table_search(ctx->write_jobs, prsc);
113    if (!entry)
114       return;
115 
116    struct lima_job *job = entry->data;
117    if (job->key.zsbuf && (job->key.zsbuf->texture == prsc))
118       job->resolve &= ~(PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL);
119 
120    if (job->key.cbuf && (job->key.cbuf->texture == prsc))
121       job->resolve &= ~PIPE_CLEAR_COLOR0;
122 
123    _mesa_hash_table_remove_key(ctx->write_jobs, prsc);
124 }
125 
126 static void
plb_pp_stream_delete_fn(struct hash_entry * entry)127 plb_pp_stream_delete_fn(struct hash_entry *entry)
128 {
129    struct lima_ctx_plb_pp_stream *s = entry->data;
130 
131    lima_bo_unreference(s->bo);
132    list_del(&s->lru_list);
133    ralloc_free(s);
134 }
135 
136 static void
lima_context_destroy(struct pipe_context * pctx)137 lima_context_destroy(struct pipe_context *pctx)
138 {
139    struct lima_context *ctx = lima_context(pctx);
140    struct lima_screen *screen = lima_screen(pctx->screen);
141 
142    if (ctx->jobs)
143       lima_job_fini(ctx);
144 
145    for (int i = 0; i < lima_ctx_buff_num; i++)
146       pipe_resource_reference(&ctx->buffer_state[i].res, NULL);
147 
148    lima_program_fini(ctx);
149    lima_state_fini(ctx);
150    util_unreference_framebuffer_state(&ctx->framebuffer.base);
151 
152    if (ctx->blitter)
153       util_blitter_destroy(ctx->blitter);
154 
155    if (ctx->uploader)
156       u_upload_destroy(ctx->uploader);
157 
158    slab_destroy_child(&ctx->transfer_pool);
159 
160    for (int i = 0; i < LIMA_CTX_PLB_MAX_NUM; i++) {
161       if (ctx->plb[i])
162          lima_bo_unreference(ctx->plb[i]);
163       if (ctx->gp_tile_heap[i])
164          lima_bo_unreference(ctx->gp_tile_heap[i]);
165    }
166 
167    if (ctx->plb_gp_stream)
168       lima_bo_unreference(ctx->plb_gp_stream);
169 
170    if (ctx->gp_output)
171       lima_bo_unreference(ctx->gp_output);
172 
173    _mesa_hash_table_destroy(ctx->plb_pp_stream,
174                             plb_pp_stream_delete_fn);
175 
176    lima_context_free_drm_ctx(screen, ctx->id);
177 
178    ralloc_free(ctx);
179 }
180 
181 static uint32_t
plb_pp_stream_hash(const void * key)182 plb_pp_stream_hash(const void *key)
183 {
184    return _mesa_hash_data(key, sizeof(struct lima_ctx_plb_pp_stream_key));
185 }
186 
187 static bool
plb_pp_stream_compare(const void * key1,const void * key2)188 plb_pp_stream_compare(const void *key1, const void *key2)
189 {
190    return memcmp(key1, key2, sizeof(struct lima_ctx_plb_pp_stream_key)) == 0;
191 }
192 
193 struct pipe_context *
lima_context_create(struct pipe_screen * pscreen,void * priv,unsigned flags)194 lima_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
195 {
196    struct lima_screen *screen = lima_screen(pscreen);
197    struct lima_context *ctx;
198 
199    ctx = rzalloc(NULL, struct lima_context);
200    if (!ctx)
201       return NULL;
202 
203    ctx->id = lima_context_create_drm_ctx(screen);
204    if (ctx->id < 0) {
205       ralloc_free(ctx);
206       return NULL;
207    }
208 
209    ctx->sample_mask = (1 << LIMA_MAX_SAMPLES) - 1;
210 
211    ctx->base.screen = pscreen;
212    ctx->base.destroy = lima_context_destroy;
213    ctx->base.set_debug_callback = u_default_set_debug_callback;
214    ctx->base.invalidate_resource = lima_invalidate_resource;
215 
216    lima_resource_context_init(ctx);
217    lima_fence_context_init(ctx);
218    lima_state_init(ctx);
219    lima_draw_init(ctx);
220    lima_program_init(ctx);
221    lima_query_init(ctx);
222 
223    slab_create_child(&ctx->transfer_pool, &screen->transfer_pool);
224 
225    ctx->blitter = util_blitter_create(&ctx->base);
226    if (!ctx->blitter)
227       goto err_out;
228 
229    ctx->uploader = u_upload_create_default(&ctx->base);
230    if (!ctx->uploader)
231       goto err_out;
232    ctx->base.stream_uploader = ctx->uploader;
233    ctx->base.const_uploader = ctx->uploader;
234 
235    ctx->plb_size = screen->plb_max_blk * LIMA_CTX_PLB_BLK_SIZE;
236    ctx->plb_gp_size = screen->plb_max_blk * 4;
237 
238    uint32_t heap_flags;
239    if (screen->has_growable_heap_buffer) {
240       /* growable size buffer, initially will allocate 32K (by default)
241        * backup memory in kernel driver, and will allocate more when GP
242        * get out of memory interrupt. Max to 16M set here.
243        */
244       ctx->gp_tile_heap_size = 0x1000000;
245       heap_flags = LIMA_BO_FLAG_HEAP;
246    } else {
247       /* fix size buffer */
248       ctx->gp_tile_heap_size = 0x100000;
249       heap_flags = 0;
250    }
251 
252    for (int i = 0; i < lima_ctx_num_plb; i++) {
253       ctx->plb[i] = lima_bo_create(screen, ctx->plb_size, 0);
254       if (!ctx->plb[i])
255          goto err_out;
256       ctx->gp_tile_heap[i] = lima_bo_create(screen, ctx->gp_tile_heap_size, heap_flags);
257       if (!ctx->gp_tile_heap[i])
258          goto err_out;
259    }
260 
261    unsigned plb_gp_stream_size =
262       align(ctx->plb_gp_size * lima_ctx_num_plb, LIMA_PAGE_SIZE);
263    ctx->plb_gp_stream =
264       lima_bo_create(screen, plb_gp_stream_size, 0);
265    if (!ctx->plb_gp_stream)
266       goto err_out;
267    lima_bo_map(ctx->plb_gp_stream);
268 
269    /* plb gp stream is static for any framebuffer */
270    for (int i = 0; i < lima_ctx_num_plb; i++) {
271       uint32_t *plb_gp_stream = ctx->plb_gp_stream->map + i * ctx->plb_gp_size;
272       for (int j = 0; j < screen->plb_max_blk; j++)
273          plb_gp_stream[j] = ctx->plb[i]->va + LIMA_CTX_PLB_BLK_SIZE * j;
274    }
275 
276    list_inithead(&ctx->plb_pp_stream_lru_list);
277    ctx->plb_pp_stream = _mesa_hash_table_create(
278       ctx, plb_pp_stream_hash, plb_pp_stream_compare);
279    if (!ctx->plb_pp_stream)
280       goto err_out;
281 
282    if (!lima_job_init(ctx))
283       goto err_out;
284 
285    return &ctx->base;
286 
287 err_out:
288    lima_context_destroy(&ctx->base);
289    return NULL;
290 }
291