xref: /aosp_15_r20/external/virglrenderer/server/render_context.c (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
1*bbecb9d1SAndroid Build Coastguard Worker /*
2*bbecb9d1SAndroid Build Coastguard Worker  * Copyright 2021 Google LLC
3*bbecb9d1SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*bbecb9d1SAndroid Build Coastguard Worker  */
5*bbecb9d1SAndroid Build Coastguard Worker 
6*bbecb9d1SAndroid Build Coastguard Worker #include "render_context.h"
7*bbecb9d1SAndroid Build Coastguard Worker 
8*bbecb9d1SAndroid Build Coastguard Worker #include <sys/mman.h>
9*bbecb9d1SAndroid Build Coastguard Worker 
10*bbecb9d1SAndroid Build Coastguard Worker #include "util/u_thread.h"
11*bbecb9d1SAndroid Build Coastguard Worker #include "virgl_util.h"
12*bbecb9d1SAndroid Build Coastguard Worker #include "virglrenderer.h"
13*bbecb9d1SAndroid Build Coastguard Worker #include "vrend_iov.h"
14*bbecb9d1SAndroid Build Coastguard Worker 
15*bbecb9d1SAndroid Build Coastguard Worker #include "render_virgl.h"
16*bbecb9d1SAndroid Build Coastguard Worker 
17*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_import_resource(struct render_context * ctx,const struct render_context_op_import_resource_request * req,int res_fd)18*bbecb9d1SAndroid Build Coastguard Worker render_context_import_resource(struct render_context *ctx,
19*bbecb9d1SAndroid Build Coastguard Worker                                const struct render_context_op_import_resource_request *req,
20*bbecb9d1SAndroid Build Coastguard Worker                                int res_fd)
21*bbecb9d1SAndroid Build Coastguard Worker {
22*bbecb9d1SAndroid Build Coastguard Worker    const uint32_t res_id = req->res_id;
23*bbecb9d1SAndroid Build Coastguard Worker    const enum virgl_resource_fd_type fd_type = req->fd_type;
24*bbecb9d1SAndroid Build Coastguard Worker    const uint64_t size = req->size;
25*bbecb9d1SAndroid Build Coastguard Worker 
26*bbecb9d1SAndroid Build Coastguard Worker    if (fd_type == VIRGL_RESOURCE_FD_INVALID || !size) {
27*bbecb9d1SAndroid Build Coastguard Worker       render_log("failed to attach invalid resource %d", res_id);
28*bbecb9d1SAndroid Build Coastguard Worker       return false;
29*bbecb9d1SAndroid Build Coastguard Worker    }
30*bbecb9d1SAndroid Build Coastguard Worker 
31*bbecb9d1SAndroid Build Coastguard Worker    uint32_t import_fd_type;
32*bbecb9d1SAndroid Build Coastguard Worker    switch (fd_type) {
33*bbecb9d1SAndroid Build Coastguard Worker    case VIRGL_RESOURCE_FD_DMABUF:
34*bbecb9d1SAndroid Build Coastguard Worker       import_fd_type = VIRGL_RENDERER_BLOB_FD_TYPE_DMABUF;
35*bbecb9d1SAndroid Build Coastguard Worker       break;
36*bbecb9d1SAndroid Build Coastguard Worker    case VIRGL_RESOURCE_FD_OPAQUE:
37*bbecb9d1SAndroid Build Coastguard Worker       import_fd_type = VIRGL_RENDERER_BLOB_FD_TYPE_OPAQUE;
38*bbecb9d1SAndroid Build Coastguard Worker       break;
39*bbecb9d1SAndroid Build Coastguard Worker    case VIRGL_RESOURCE_FD_SHM:
40*bbecb9d1SAndroid Build Coastguard Worker       import_fd_type = VIRGL_RENDERER_BLOB_FD_TYPE_SHM;
41*bbecb9d1SAndroid Build Coastguard Worker       break;
42*bbecb9d1SAndroid Build Coastguard Worker    default:
43*bbecb9d1SAndroid Build Coastguard Worker       import_fd_type = 0;
44*bbecb9d1SAndroid Build Coastguard Worker       break;
45*bbecb9d1SAndroid Build Coastguard Worker    }
46*bbecb9d1SAndroid Build Coastguard Worker    const struct virgl_renderer_resource_import_blob_args import_args = {
47*bbecb9d1SAndroid Build Coastguard Worker       .res_handle = res_id,
48*bbecb9d1SAndroid Build Coastguard Worker       .blob_mem = VIRGL_RENDERER_BLOB_MEM_HOST3D,
49*bbecb9d1SAndroid Build Coastguard Worker       .fd_type = import_fd_type,
50*bbecb9d1SAndroid Build Coastguard Worker       .fd = res_fd,
51*bbecb9d1SAndroid Build Coastguard Worker       .size = size,
52*bbecb9d1SAndroid Build Coastguard Worker    };
53*bbecb9d1SAndroid Build Coastguard Worker 
54*bbecb9d1SAndroid Build Coastguard Worker    int ret = virgl_renderer_resource_import_blob(&import_args);
55*bbecb9d1SAndroid Build Coastguard Worker    if (ret) {
56*bbecb9d1SAndroid Build Coastguard Worker       render_log("failed to import blob resource %d (%d)", res_id, ret);
57*bbecb9d1SAndroid Build Coastguard Worker       return false;
58*bbecb9d1SAndroid Build Coastguard Worker    }
59*bbecb9d1SAndroid Build Coastguard Worker 
60*bbecb9d1SAndroid Build Coastguard Worker    virgl_renderer_ctx_attach_resource(ctx->ctx_id, res_id);
61*bbecb9d1SAndroid Build Coastguard Worker 
62*bbecb9d1SAndroid Build Coastguard Worker    return true;
63*bbecb9d1SAndroid Build Coastguard Worker }
64*bbecb9d1SAndroid Build Coastguard Worker 
65*bbecb9d1SAndroid Build Coastguard Worker void
render_context_update_timeline(struct render_context * ctx,uint32_t ring_idx,uint32_t seqno)66*bbecb9d1SAndroid Build Coastguard Worker render_context_update_timeline(struct render_context *ctx,
67*bbecb9d1SAndroid Build Coastguard Worker                                uint32_t ring_idx,
68*bbecb9d1SAndroid Build Coastguard Worker                                uint32_t seqno)
69*bbecb9d1SAndroid Build Coastguard Worker {
70*bbecb9d1SAndroid Build Coastguard Worker    /* this can be called by the context's main thread and sync threads */
71*bbecb9d1SAndroid Build Coastguard Worker    atomic_store(&ctx->shmem_timelines[ring_idx], seqno);
72*bbecb9d1SAndroid Build Coastguard Worker    if (ctx->fence_eventfd >= 0)
73*bbecb9d1SAndroid Build Coastguard Worker       write_eventfd(ctx->fence_eventfd, 1);
74*bbecb9d1SAndroid Build Coastguard Worker }
75*bbecb9d1SAndroid Build Coastguard Worker 
76*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_init_virgl_context(struct render_context * ctx,const struct render_context_op_init_request * req,int shmem_fd,int fence_eventfd)77*bbecb9d1SAndroid Build Coastguard Worker render_context_init_virgl_context(struct render_context *ctx,
78*bbecb9d1SAndroid Build Coastguard Worker                                   const struct render_context_op_init_request *req,
79*bbecb9d1SAndroid Build Coastguard Worker                                   int shmem_fd,
80*bbecb9d1SAndroid Build Coastguard Worker                                   int fence_eventfd)
81*bbecb9d1SAndroid Build Coastguard Worker {
82*bbecb9d1SAndroid Build Coastguard Worker    const int timeline_count = req->shmem_size / sizeof(*ctx->shmem_timelines);
83*bbecb9d1SAndroid Build Coastguard Worker 
84*bbecb9d1SAndroid Build Coastguard Worker    void *shmem_ptr = mmap(NULL, req->shmem_size, PROT_WRITE, MAP_SHARED, shmem_fd, 0);
85*bbecb9d1SAndroid Build Coastguard Worker    if (shmem_ptr == MAP_FAILED)
86*bbecb9d1SAndroid Build Coastguard Worker       return false;
87*bbecb9d1SAndroid Build Coastguard Worker 
88*bbecb9d1SAndroid Build Coastguard Worker    int ret = virgl_renderer_context_create_with_flags(ctx->ctx_id, req->flags,
89*bbecb9d1SAndroid Build Coastguard Worker                                                       ctx->name_len, ctx->name);
90*bbecb9d1SAndroid Build Coastguard Worker    if (ret) {
91*bbecb9d1SAndroid Build Coastguard Worker       munmap(shmem_ptr, req->shmem_size);
92*bbecb9d1SAndroid Build Coastguard Worker       return false;
93*bbecb9d1SAndroid Build Coastguard Worker    }
94*bbecb9d1SAndroid Build Coastguard Worker 
95*bbecb9d1SAndroid Build Coastguard Worker    ctx->shmem_fd = shmem_fd;
96*bbecb9d1SAndroid Build Coastguard Worker    ctx->shmem_size = req->shmem_size;
97*bbecb9d1SAndroid Build Coastguard Worker    ctx->shmem_ptr = shmem_ptr;
98*bbecb9d1SAndroid Build Coastguard Worker    ctx->shmem_timelines = shmem_ptr;
99*bbecb9d1SAndroid Build Coastguard Worker 
100*bbecb9d1SAndroid Build Coastguard Worker    for (int i = 0; i < timeline_count; i++)
101*bbecb9d1SAndroid Build Coastguard Worker       atomic_store(&ctx->shmem_timelines[i], 0);
102*bbecb9d1SAndroid Build Coastguard Worker 
103*bbecb9d1SAndroid Build Coastguard Worker    ctx->timeline_count = timeline_count;
104*bbecb9d1SAndroid Build Coastguard Worker 
105*bbecb9d1SAndroid Build Coastguard Worker    ctx->fence_eventfd = fence_eventfd;
106*bbecb9d1SAndroid Build Coastguard Worker 
107*bbecb9d1SAndroid Build Coastguard Worker    return true;
108*bbecb9d1SAndroid Build Coastguard Worker }
109*bbecb9d1SAndroid Build Coastguard Worker 
110*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_create_resource(struct render_context * ctx,const struct render_context_op_create_resource_request * req,enum virgl_resource_fd_type * out_fd_type,uint32_t * out_map_info,int * out_res_fd)111*bbecb9d1SAndroid Build Coastguard Worker render_context_create_resource(struct render_context *ctx,
112*bbecb9d1SAndroid Build Coastguard Worker                                const struct render_context_op_create_resource_request *req,
113*bbecb9d1SAndroid Build Coastguard Worker                                enum virgl_resource_fd_type *out_fd_type,
114*bbecb9d1SAndroid Build Coastguard Worker                                uint32_t *out_map_info,
115*bbecb9d1SAndroid Build Coastguard Worker                                int *out_res_fd)
116*bbecb9d1SAndroid Build Coastguard Worker {
117*bbecb9d1SAndroid Build Coastguard Worker    const uint32_t res_id = req->res_id;
118*bbecb9d1SAndroid Build Coastguard Worker    const struct virgl_renderer_resource_create_blob_args blob_args = {
119*bbecb9d1SAndroid Build Coastguard Worker       .res_handle = res_id,
120*bbecb9d1SAndroid Build Coastguard Worker       .ctx_id = ctx->ctx_id,
121*bbecb9d1SAndroid Build Coastguard Worker       .blob_mem = VIRGL_RENDERER_BLOB_MEM_HOST3D,
122*bbecb9d1SAndroid Build Coastguard Worker       .blob_flags = req->blob_flags,
123*bbecb9d1SAndroid Build Coastguard Worker       .blob_id = req->blob_id,
124*bbecb9d1SAndroid Build Coastguard Worker       .size = req->blob_size,
125*bbecb9d1SAndroid Build Coastguard Worker    };
126*bbecb9d1SAndroid Build Coastguard Worker    int ret = virgl_renderer_resource_create_blob(&blob_args);
127*bbecb9d1SAndroid Build Coastguard Worker    if (ret) {
128*bbecb9d1SAndroid Build Coastguard Worker       render_log("failed to create blob resource");
129*bbecb9d1SAndroid Build Coastguard Worker       return false;
130*bbecb9d1SAndroid Build Coastguard Worker    }
131*bbecb9d1SAndroid Build Coastguard Worker 
132*bbecb9d1SAndroid Build Coastguard Worker    uint32_t map_info;
133*bbecb9d1SAndroid Build Coastguard Worker    ret = virgl_renderer_resource_get_map_info(res_id, &map_info);
134*bbecb9d1SAndroid Build Coastguard Worker    if (ret) {
135*bbecb9d1SAndroid Build Coastguard Worker       /* properly set map_info when the resource has no map cache info */
136*bbecb9d1SAndroid Build Coastguard Worker       map_info = VIRGL_RENDERER_MAP_CACHE_NONE;
137*bbecb9d1SAndroid Build Coastguard Worker    }
138*bbecb9d1SAndroid Build Coastguard Worker 
139*bbecb9d1SAndroid Build Coastguard Worker    uint32_t fd_type;
140*bbecb9d1SAndroid Build Coastguard Worker    int res_fd;
141*bbecb9d1SAndroid Build Coastguard Worker    ret = virgl_renderer_resource_export_blob(res_id, &fd_type, &res_fd);
142*bbecb9d1SAndroid Build Coastguard Worker    if (ret) {
143*bbecb9d1SAndroid Build Coastguard Worker       virgl_renderer_resource_unref(res_id);
144*bbecb9d1SAndroid Build Coastguard Worker       return false;
145*bbecb9d1SAndroid Build Coastguard Worker    }
146*bbecb9d1SAndroid Build Coastguard Worker 
147*bbecb9d1SAndroid Build Coastguard Worker    /* RENDER_CONTEXT_OP_CREATE_RESOURCE implies attach and proxy will not send
148*bbecb9d1SAndroid Build Coastguard Worker     * RENDER_CONTEXT_OP_IMPORT_RESOURCE to attach the resource again.
149*bbecb9d1SAndroid Build Coastguard Worker     */
150*bbecb9d1SAndroid Build Coastguard Worker    virgl_renderer_ctx_attach_resource(ctx->ctx_id, res_id);
151*bbecb9d1SAndroid Build Coastguard Worker 
152*bbecb9d1SAndroid Build Coastguard Worker    switch (fd_type) {
153*bbecb9d1SAndroid Build Coastguard Worker    case VIRGL_RENDERER_BLOB_FD_TYPE_DMABUF:
154*bbecb9d1SAndroid Build Coastguard Worker       *out_fd_type = VIRGL_RESOURCE_FD_DMABUF;
155*bbecb9d1SAndroid Build Coastguard Worker       break;
156*bbecb9d1SAndroid Build Coastguard Worker    case VIRGL_RENDERER_BLOB_FD_TYPE_OPAQUE:
157*bbecb9d1SAndroid Build Coastguard Worker       *out_fd_type = VIRGL_RESOURCE_FD_OPAQUE;
158*bbecb9d1SAndroid Build Coastguard Worker       break;
159*bbecb9d1SAndroid Build Coastguard Worker    case VIRGL_RENDERER_BLOB_FD_TYPE_SHM:
160*bbecb9d1SAndroid Build Coastguard Worker       *out_fd_type = VIRGL_RESOURCE_FD_SHM;
161*bbecb9d1SAndroid Build Coastguard Worker       break;
162*bbecb9d1SAndroid Build Coastguard Worker    default:
163*bbecb9d1SAndroid Build Coastguard Worker       *out_fd_type = 0;
164*bbecb9d1SAndroid Build Coastguard Worker    }
165*bbecb9d1SAndroid Build Coastguard Worker 
166*bbecb9d1SAndroid Build Coastguard Worker    *out_map_info = map_info;
167*bbecb9d1SAndroid Build Coastguard Worker    *out_res_fd = res_fd;
168*bbecb9d1SAndroid Build Coastguard Worker 
169*bbecb9d1SAndroid Build Coastguard Worker    return true;
170*bbecb9d1SAndroid Build Coastguard Worker }
171*bbecb9d1SAndroid Build Coastguard Worker 
172*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_dispatch_submit_fence(struct render_context * ctx,const union render_context_op_request * req,UNUSED const int * fds,UNUSED int fd_count)173*bbecb9d1SAndroid Build Coastguard Worker render_context_dispatch_submit_fence(struct render_context *ctx,
174*bbecb9d1SAndroid Build Coastguard Worker                                      const union render_context_op_request *req,
175*bbecb9d1SAndroid Build Coastguard Worker                                      UNUSED const int *fds,
176*bbecb9d1SAndroid Build Coastguard Worker                                      UNUSED int fd_count)
177*bbecb9d1SAndroid Build Coastguard Worker {
178*bbecb9d1SAndroid Build Coastguard Worker    /* always merge fences */
179*bbecb9d1SAndroid Build Coastguard Worker    assert(!(req->submit_fence.flags & ~VIRGL_RENDERER_FENCE_FLAG_MERGEABLE));
180*bbecb9d1SAndroid Build Coastguard Worker    const uint32_t flags = VIRGL_RENDERER_FENCE_FLAG_MERGEABLE;
181*bbecb9d1SAndroid Build Coastguard Worker    const uint32_t ring_idx = req->submit_fence.ring_index;
182*bbecb9d1SAndroid Build Coastguard Worker    const uint32_t seqno = req->submit_fence.seqno;
183*bbecb9d1SAndroid Build Coastguard Worker 
184*bbecb9d1SAndroid Build Coastguard Worker    assert(ring_idx < (uint32_t)ctx->timeline_count);
185*bbecb9d1SAndroid Build Coastguard Worker    int ret = virgl_renderer_context_create_fence(ctx->ctx_id, flags, ring_idx, seqno);
186*bbecb9d1SAndroid Build Coastguard Worker 
187*bbecb9d1SAndroid Build Coastguard Worker    return !ret;
188*bbecb9d1SAndroid Build Coastguard Worker }
189*bbecb9d1SAndroid Build Coastguard Worker 
190*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_dispatch_submit_cmd(struct render_context * ctx,const union render_context_op_request * req,UNUSED const int * fds,UNUSED int fd_count)191*bbecb9d1SAndroid Build Coastguard Worker render_context_dispatch_submit_cmd(struct render_context *ctx,
192*bbecb9d1SAndroid Build Coastguard Worker                                    const union render_context_op_request *req,
193*bbecb9d1SAndroid Build Coastguard Worker                                    UNUSED const int *fds,
194*bbecb9d1SAndroid Build Coastguard Worker                                    UNUSED int fd_count)
195*bbecb9d1SAndroid Build Coastguard Worker {
196*bbecb9d1SAndroid Build Coastguard Worker    const int ndw = req->submit_cmd.size / sizeof(uint32_t);
197*bbecb9d1SAndroid Build Coastguard Worker    void *cmd = (void *)req->submit_cmd.cmd;
198*bbecb9d1SAndroid Build Coastguard Worker    if (req->submit_cmd.size > sizeof(req->submit_cmd.cmd)) {
199*bbecb9d1SAndroid Build Coastguard Worker       cmd = malloc(req->submit_cmd.size);
200*bbecb9d1SAndroid Build Coastguard Worker       if (!cmd)
201*bbecb9d1SAndroid Build Coastguard Worker          return true;
202*bbecb9d1SAndroid Build Coastguard Worker 
203*bbecb9d1SAndroid Build Coastguard Worker       const size_t inlined = sizeof(req->submit_cmd.cmd);
204*bbecb9d1SAndroid Build Coastguard Worker       const size_t remain = req->submit_cmd.size - inlined;
205*bbecb9d1SAndroid Build Coastguard Worker 
206*bbecb9d1SAndroid Build Coastguard Worker       memcpy(cmd, req->submit_cmd.cmd, inlined);
207*bbecb9d1SAndroid Build Coastguard Worker       if (!render_socket_receive_data(&ctx->socket, (char *)cmd + inlined, remain)) {
208*bbecb9d1SAndroid Build Coastguard Worker          free(cmd);
209*bbecb9d1SAndroid Build Coastguard Worker          return false;
210*bbecb9d1SAndroid Build Coastguard Worker       }
211*bbecb9d1SAndroid Build Coastguard Worker    }
212*bbecb9d1SAndroid Build Coastguard Worker 
213*bbecb9d1SAndroid Build Coastguard Worker    int ret = virgl_renderer_submit_cmd(cmd, ctx->ctx_id, ndw);
214*bbecb9d1SAndroid Build Coastguard Worker 
215*bbecb9d1SAndroid Build Coastguard Worker    if (cmd != req->submit_cmd.cmd)
216*bbecb9d1SAndroid Build Coastguard Worker       free(cmd);
217*bbecb9d1SAndroid Build Coastguard Worker 
218*bbecb9d1SAndroid Build Coastguard Worker    const struct render_context_op_submit_cmd_reply reply = {
219*bbecb9d1SAndroid Build Coastguard Worker       .ok = !ret,
220*bbecb9d1SAndroid Build Coastguard Worker    };
221*bbecb9d1SAndroid Build Coastguard Worker    if (!render_socket_send_reply(&ctx->socket, &reply, sizeof(reply)))
222*bbecb9d1SAndroid Build Coastguard Worker       return false;
223*bbecb9d1SAndroid Build Coastguard Worker 
224*bbecb9d1SAndroid Build Coastguard Worker    return true;
225*bbecb9d1SAndroid Build Coastguard Worker }
226*bbecb9d1SAndroid Build Coastguard Worker 
227*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_dispatch_create_resource(struct render_context * ctx,const union render_context_op_request * req,UNUSED const int * fds,UNUSED int fd_count)228*bbecb9d1SAndroid Build Coastguard Worker render_context_dispatch_create_resource(struct render_context *ctx,
229*bbecb9d1SAndroid Build Coastguard Worker                                         const union render_context_op_request *req,
230*bbecb9d1SAndroid Build Coastguard Worker                                         UNUSED const int *fds,
231*bbecb9d1SAndroid Build Coastguard Worker                                         UNUSED int fd_count)
232*bbecb9d1SAndroid Build Coastguard Worker {
233*bbecb9d1SAndroid Build Coastguard Worker    struct render_context_op_create_resource_reply reply = {
234*bbecb9d1SAndroid Build Coastguard Worker       .fd_type = VIRGL_RESOURCE_FD_INVALID,
235*bbecb9d1SAndroid Build Coastguard Worker    };
236*bbecb9d1SAndroid Build Coastguard Worker    int res_fd;
237*bbecb9d1SAndroid Build Coastguard Worker    bool ok = render_context_create_resource(ctx, &req->create_resource, &reply.fd_type,
238*bbecb9d1SAndroid Build Coastguard Worker                                             &reply.map_info, &res_fd);
239*bbecb9d1SAndroid Build Coastguard Worker    if (!ok)
240*bbecb9d1SAndroid Build Coastguard Worker       return render_socket_send_reply(&ctx->socket, &reply, sizeof(reply));
241*bbecb9d1SAndroid Build Coastguard Worker 
242*bbecb9d1SAndroid Build Coastguard Worker    ok =
243*bbecb9d1SAndroid Build Coastguard Worker       render_socket_send_reply_with_fds(&ctx->socket, &reply, sizeof(reply), &res_fd, 1);
244*bbecb9d1SAndroid Build Coastguard Worker    close(res_fd);
245*bbecb9d1SAndroid Build Coastguard Worker 
246*bbecb9d1SAndroid Build Coastguard Worker    return ok;
247*bbecb9d1SAndroid Build Coastguard Worker }
248*bbecb9d1SAndroid Build Coastguard Worker 
249*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_dispatch_destroy_resource(UNUSED struct render_context * ctx,const union render_context_op_request * req,UNUSED const int * fds,UNUSED int fd_count)250*bbecb9d1SAndroid Build Coastguard Worker render_context_dispatch_destroy_resource(UNUSED struct render_context *ctx,
251*bbecb9d1SAndroid Build Coastguard Worker                                          const union render_context_op_request *req,
252*bbecb9d1SAndroid Build Coastguard Worker                                          UNUSED const int *fds,
253*bbecb9d1SAndroid Build Coastguard Worker                                          UNUSED int fd_count)
254*bbecb9d1SAndroid Build Coastguard Worker {
255*bbecb9d1SAndroid Build Coastguard Worker    virgl_renderer_resource_unref(req->destroy_resource.res_id);
256*bbecb9d1SAndroid Build Coastguard Worker    return true;
257*bbecb9d1SAndroid Build Coastguard Worker }
258*bbecb9d1SAndroid Build Coastguard Worker 
259*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_dispatch_import_resource(struct render_context * ctx,const union render_context_op_request * req,const int * fds,int fd_count)260*bbecb9d1SAndroid Build Coastguard Worker render_context_dispatch_import_resource(struct render_context *ctx,
261*bbecb9d1SAndroid Build Coastguard Worker                                         const union render_context_op_request *req,
262*bbecb9d1SAndroid Build Coastguard Worker                                         const int *fds,
263*bbecb9d1SAndroid Build Coastguard Worker                                         int fd_count)
264*bbecb9d1SAndroid Build Coastguard Worker {
265*bbecb9d1SAndroid Build Coastguard Worker    if (fd_count != 1) {
266*bbecb9d1SAndroid Build Coastguard Worker       render_log("failed to attach resource with fd_count %d", fd_count);
267*bbecb9d1SAndroid Build Coastguard Worker       return false;
268*bbecb9d1SAndroid Build Coastguard Worker    }
269*bbecb9d1SAndroid Build Coastguard Worker 
270*bbecb9d1SAndroid Build Coastguard Worker    /* classic 3d resource with valid size reuses the blob import path here */
271*bbecb9d1SAndroid Build Coastguard Worker    return render_context_import_resource(ctx, &req->import_resource, fds[0]);
272*bbecb9d1SAndroid Build Coastguard Worker }
273*bbecb9d1SAndroid Build Coastguard Worker 
274*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_dispatch_init(struct render_context * ctx,const union render_context_op_request * req,const int * fds,int fd_count)275*bbecb9d1SAndroid Build Coastguard Worker render_context_dispatch_init(struct render_context *ctx,
276*bbecb9d1SAndroid Build Coastguard Worker                              const union render_context_op_request *req,
277*bbecb9d1SAndroid Build Coastguard Worker                              const int *fds,
278*bbecb9d1SAndroid Build Coastguard Worker                              int fd_count)
279*bbecb9d1SAndroid Build Coastguard Worker {
280*bbecb9d1SAndroid Build Coastguard Worker    if (fd_count != 1 && fd_count != 2)
281*bbecb9d1SAndroid Build Coastguard Worker       return false;
282*bbecb9d1SAndroid Build Coastguard Worker 
283*bbecb9d1SAndroid Build Coastguard Worker    const int shmem_fd = fds[0];
284*bbecb9d1SAndroid Build Coastguard Worker    const int fence_eventfd = fd_count == 2 ? fds[1] : -1;
285*bbecb9d1SAndroid Build Coastguard Worker    return render_context_init_virgl_context(ctx, &req->init, shmem_fd, fence_eventfd);
286*bbecb9d1SAndroid Build Coastguard Worker }
287*bbecb9d1SAndroid Build Coastguard Worker 
288*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_dispatch_nop(UNUSED struct render_context * ctx,UNUSED const union render_context_op_request * req,UNUSED const int * fds,UNUSED int fd_count)289*bbecb9d1SAndroid Build Coastguard Worker render_context_dispatch_nop(UNUSED struct render_context *ctx,
290*bbecb9d1SAndroid Build Coastguard Worker                             UNUSED const union render_context_op_request *req,
291*bbecb9d1SAndroid Build Coastguard Worker                             UNUSED const int *fds,
292*bbecb9d1SAndroid Build Coastguard Worker                             UNUSED int fd_count)
293*bbecb9d1SAndroid Build Coastguard Worker {
294*bbecb9d1SAndroid Build Coastguard Worker    return true;
295*bbecb9d1SAndroid Build Coastguard Worker }
296*bbecb9d1SAndroid Build Coastguard Worker 
297*bbecb9d1SAndroid Build Coastguard Worker struct render_context_dispatch_entry {
298*bbecb9d1SAndroid Build Coastguard Worker    size_t expect_size;
299*bbecb9d1SAndroid Build Coastguard Worker    int max_fd_count;
300*bbecb9d1SAndroid Build Coastguard Worker    bool (*dispatch)(struct render_context *ctx,
301*bbecb9d1SAndroid Build Coastguard Worker                     const union render_context_op_request *req,
302*bbecb9d1SAndroid Build Coastguard Worker                     const int *fds,
303*bbecb9d1SAndroid Build Coastguard Worker                     int fd_count);
304*bbecb9d1SAndroid Build Coastguard Worker };
305*bbecb9d1SAndroid Build Coastguard Worker 
306*bbecb9d1SAndroid Build Coastguard Worker static const struct render_context_dispatch_entry
307*bbecb9d1SAndroid Build Coastguard Worker    render_context_dispatch_table[RENDER_CONTEXT_OP_COUNT] = {
308*bbecb9d1SAndroid Build Coastguard Worker #define RENDER_CONTEXT_DISPATCH(NAME, name, max_fd)                                      \
309*bbecb9d1SAndroid Build Coastguard Worker    [RENDER_CONTEXT_OP_##                                                                 \
310*bbecb9d1SAndroid Build Coastguard Worker       NAME] = { .expect_size = sizeof(struct render_context_op_##name##_request),        \
311*bbecb9d1SAndroid Build Coastguard Worker                 .max_fd_count = (max_fd),                                                \
312*bbecb9d1SAndroid Build Coastguard Worker                 .dispatch = render_context_dispatch_##name }
313*bbecb9d1SAndroid Build Coastguard Worker       RENDER_CONTEXT_DISPATCH(NOP, nop, 0),
314*bbecb9d1SAndroid Build Coastguard Worker       RENDER_CONTEXT_DISPATCH(INIT, init, 2),
315*bbecb9d1SAndroid Build Coastguard Worker       RENDER_CONTEXT_DISPATCH(CREATE_RESOURCE, create_resource, 0),
316*bbecb9d1SAndroid Build Coastguard Worker       RENDER_CONTEXT_DISPATCH(IMPORT_RESOURCE, import_resource, 1),
317*bbecb9d1SAndroid Build Coastguard Worker       RENDER_CONTEXT_DISPATCH(DESTROY_RESOURCE, destroy_resource, 0),
318*bbecb9d1SAndroid Build Coastguard Worker       RENDER_CONTEXT_DISPATCH(SUBMIT_CMD, submit_cmd, 0),
319*bbecb9d1SAndroid Build Coastguard Worker       RENDER_CONTEXT_DISPATCH(SUBMIT_FENCE, submit_fence, 0),
320*bbecb9d1SAndroid Build Coastguard Worker #undef RENDER_CONTEXT_DISPATCH
321*bbecb9d1SAndroid Build Coastguard Worker    };
322*bbecb9d1SAndroid Build Coastguard Worker 
323*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_dispatch(struct render_context * ctx)324*bbecb9d1SAndroid Build Coastguard Worker render_context_dispatch(struct render_context *ctx)
325*bbecb9d1SAndroid Build Coastguard Worker {
326*bbecb9d1SAndroid Build Coastguard Worker    union render_context_op_request req;
327*bbecb9d1SAndroid Build Coastguard Worker    size_t req_size;
328*bbecb9d1SAndroid Build Coastguard Worker    int req_fds[8];
329*bbecb9d1SAndroid Build Coastguard Worker    int req_fd_count;
330*bbecb9d1SAndroid Build Coastguard Worker    if (!render_socket_receive_request_with_fds(&ctx->socket, &req, sizeof(req), &req_size,
331*bbecb9d1SAndroid Build Coastguard Worker                                                req_fds, ARRAY_SIZE(req_fds),
332*bbecb9d1SAndroid Build Coastguard Worker                                                &req_fd_count))
333*bbecb9d1SAndroid Build Coastguard Worker       return false;
334*bbecb9d1SAndroid Build Coastguard Worker 
335*bbecb9d1SAndroid Build Coastguard Worker    assert((unsigned int)req_fd_count <= ARRAY_SIZE(req_fds));
336*bbecb9d1SAndroid Build Coastguard Worker 
337*bbecb9d1SAndroid Build Coastguard Worker    if (req.header.op >= RENDER_CONTEXT_OP_COUNT) {
338*bbecb9d1SAndroid Build Coastguard Worker       render_log("invalid context op %d", req.header.op);
339*bbecb9d1SAndroid Build Coastguard Worker       goto fail;
340*bbecb9d1SAndroid Build Coastguard Worker    }
341*bbecb9d1SAndroid Build Coastguard Worker 
342*bbecb9d1SAndroid Build Coastguard Worker    const struct render_context_dispatch_entry *entry =
343*bbecb9d1SAndroid Build Coastguard Worker       &render_context_dispatch_table[req.header.op];
344*bbecb9d1SAndroid Build Coastguard Worker    if (entry->expect_size != req_size || entry->max_fd_count < req_fd_count) {
345*bbecb9d1SAndroid Build Coastguard Worker       render_log("invalid request size (%zu) or fd count (%d) for context op %d",
346*bbecb9d1SAndroid Build Coastguard Worker                  req_size, req_fd_count, req.header.op);
347*bbecb9d1SAndroid Build Coastguard Worker       goto fail;
348*bbecb9d1SAndroid Build Coastguard Worker    }
349*bbecb9d1SAndroid Build Coastguard Worker 
350*bbecb9d1SAndroid Build Coastguard Worker    render_virgl_lock_dispatch();
351*bbecb9d1SAndroid Build Coastguard Worker    const bool ok = entry->dispatch(ctx, &req, req_fds, req_fd_count);
352*bbecb9d1SAndroid Build Coastguard Worker    render_virgl_unlock_dispatch();
353*bbecb9d1SAndroid Build Coastguard Worker    if (!ok) {
354*bbecb9d1SAndroid Build Coastguard Worker       render_log("failed to dispatch context op %d", req.header.op);
355*bbecb9d1SAndroid Build Coastguard Worker       goto fail;
356*bbecb9d1SAndroid Build Coastguard Worker    }
357*bbecb9d1SAndroid Build Coastguard Worker 
358*bbecb9d1SAndroid Build Coastguard Worker    return true;
359*bbecb9d1SAndroid Build Coastguard Worker 
360*bbecb9d1SAndroid Build Coastguard Worker fail:
361*bbecb9d1SAndroid Build Coastguard Worker    for (int i = 0; i < req_fd_count; i++)
362*bbecb9d1SAndroid Build Coastguard Worker       close(req_fds[i]);
363*bbecb9d1SAndroid Build Coastguard Worker    return false;
364*bbecb9d1SAndroid Build Coastguard Worker }
365*bbecb9d1SAndroid Build Coastguard Worker 
366*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_run(struct render_context * ctx)367*bbecb9d1SAndroid Build Coastguard Worker render_context_run(struct render_context *ctx)
368*bbecb9d1SAndroid Build Coastguard Worker {
369*bbecb9d1SAndroid Build Coastguard Worker    while (true) {
370*bbecb9d1SAndroid Build Coastguard Worker       if (!render_context_dispatch(ctx))
371*bbecb9d1SAndroid Build Coastguard Worker          return false;
372*bbecb9d1SAndroid Build Coastguard Worker    }
373*bbecb9d1SAndroid Build Coastguard Worker 
374*bbecb9d1SAndroid Build Coastguard Worker    return true;
375*bbecb9d1SAndroid Build Coastguard Worker }
376*bbecb9d1SAndroid Build Coastguard Worker 
377*bbecb9d1SAndroid Build Coastguard Worker static void
render_context_fini(struct render_context * ctx)378*bbecb9d1SAndroid Build Coastguard Worker render_context_fini(struct render_context *ctx)
379*bbecb9d1SAndroid Build Coastguard Worker {
380*bbecb9d1SAndroid Build Coastguard Worker    render_virgl_lock_dispatch();
381*bbecb9d1SAndroid Build Coastguard Worker    /* destroy the context first to join its sync threads and ring threads */
382*bbecb9d1SAndroid Build Coastguard Worker    virgl_renderer_context_destroy(ctx->ctx_id);
383*bbecb9d1SAndroid Build Coastguard Worker    render_virgl_unlock_dispatch();
384*bbecb9d1SAndroid Build Coastguard Worker 
385*bbecb9d1SAndroid Build Coastguard Worker    render_virgl_remove_context(ctx);
386*bbecb9d1SAndroid Build Coastguard Worker 
387*bbecb9d1SAndroid Build Coastguard Worker    if (ctx->shmem_ptr)
388*bbecb9d1SAndroid Build Coastguard Worker       munmap(ctx->shmem_ptr, ctx->shmem_size);
389*bbecb9d1SAndroid Build Coastguard Worker    if (ctx->shmem_fd >= 0)
390*bbecb9d1SAndroid Build Coastguard Worker       close(ctx->shmem_fd);
391*bbecb9d1SAndroid Build Coastguard Worker 
392*bbecb9d1SAndroid Build Coastguard Worker    if (ctx->fence_eventfd >= 0)
393*bbecb9d1SAndroid Build Coastguard Worker       close(ctx->fence_eventfd);
394*bbecb9d1SAndroid Build Coastguard Worker 
395*bbecb9d1SAndroid Build Coastguard Worker    if (ctx->name)
396*bbecb9d1SAndroid Build Coastguard Worker       free(ctx->name);
397*bbecb9d1SAndroid Build Coastguard Worker 
398*bbecb9d1SAndroid Build Coastguard Worker    render_socket_fini(&ctx->socket);
399*bbecb9d1SAndroid Build Coastguard Worker }
400*bbecb9d1SAndroid Build Coastguard Worker 
401*bbecb9d1SAndroid Build Coastguard Worker static void
render_context_set_thread_name(uint32_t ctx_id,const char * ctx_name)402*bbecb9d1SAndroid Build Coastguard Worker render_context_set_thread_name(uint32_t ctx_id, const char *ctx_name)
403*bbecb9d1SAndroid Build Coastguard Worker {
404*bbecb9d1SAndroid Build Coastguard Worker    char thread_name[16];
405*bbecb9d1SAndroid Build Coastguard Worker    snprintf(thread_name, ARRAY_SIZE(thread_name), "virgl-%d-%s", ctx_id, ctx_name);
406*bbecb9d1SAndroid Build Coastguard Worker    u_thread_setname(thread_name);
407*bbecb9d1SAndroid Build Coastguard Worker }
408*bbecb9d1SAndroid Build Coastguard Worker 
409*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_init_name(struct render_context * ctx,uint32_t ctx_id,const char * ctx_name)410*bbecb9d1SAndroid Build Coastguard Worker render_context_init_name(struct render_context *ctx,
411*bbecb9d1SAndroid Build Coastguard Worker                          uint32_t ctx_id,
412*bbecb9d1SAndroid Build Coastguard Worker                          const char *ctx_name)
413*bbecb9d1SAndroid Build Coastguard Worker {
414*bbecb9d1SAndroid Build Coastguard Worker    ctx->name_len = strlen(ctx_name);
415*bbecb9d1SAndroid Build Coastguard Worker    ctx->name = malloc(ctx->name_len + 1);
416*bbecb9d1SAndroid Build Coastguard Worker    if (!ctx->name)
417*bbecb9d1SAndroid Build Coastguard Worker       return false;
418*bbecb9d1SAndroid Build Coastguard Worker 
419*bbecb9d1SAndroid Build Coastguard Worker    strcpy(ctx->name, ctx_name);
420*bbecb9d1SAndroid Build Coastguard Worker 
421*bbecb9d1SAndroid Build Coastguard Worker    render_context_set_thread_name(ctx_id, ctx_name);
422*bbecb9d1SAndroid Build Coastguard Worker 
423*bbecb9d1SAndroid Build Coastguard Worker #ifdef _GNU_SOURCE
424*bbecb9d1SAndroid Build Coastguard Worker    /* Sets the guest app executable name used by mesa to load app-specific driver
425*bbecb9d1SAndroid Build Coastguard Worker     * configuration. */
426*bbecb9d1SAndroid Build Coastguard Worker    program_invocation_name = ctx->name;
427*bbecb9d1SAndroid Build Coastguard Worker    program_invocation_short_name = ctx->name;
428*bbecb9d1SAndroid Build Coastguard Worker #endif
429*bbecb9d1SAndroid Build Coastguard Worker 
430*bbecb9d1SAndroid Build Coastguard Worker    return true;
431*bbecb9d1SAndroid Build Coastguard Worker }
432*bbecb9d1SAndroid Build Coastguard Worker 
433*bbecb9d1SAndroid Build Coastguard Worker static bool
render_context_init(struct render_context * ctx,const struct render_context_args * args)434*bbecb9d1SAndroid Build Coastguard Worker render_context_init(struct render_context *ctx, const struct render_context_args *args)
435*bbecb9d1SAndroid Build Coastguard Worker {
436*bbecb9d1SAndroid Build Coastguard Worker    memset(ctx, 0, sizeof(*ctx));
437*bbecb9d1SAndroid Build Coastguard Worker    ctx->ctx_id = args->ctx_id;
438*bbecb9d1SAndroid Build Coastguard Worker    render_socket_init(&ctx->socket, args->ctx_fd);
439*bbecb9d1SAndroid Build Coastguard Worker    ctx->shmem_fd = -1;
440*bbecb9d1SAndroid Build Coastguard Worker    ctx->fence_eventfd = -1;
441*bbecb9d1SAndroid Build Coastguard Worker 
442*bbecb9d1SAndroid Build Coastguard Worker    if (!render_context_init_name(ctx, args->ctx_id, args->ctx_name))
443*bbecb9d1SAndroid Build Coastguard Worker       return false;
444*bbecb9d1SAndroid Build Coastguard Worker 
445*bbecb9d1SAndroid Build Coastguard Worker    render_virgl_add_context(ctx);
446*bbecb9d1SAndroid Build Coastguard Worker 
447*bbecb9d1SAndroid Build Coastguard Worker    return true;
448*bbecb9d1SAndroid Build Coastguard Worker }
449*bbecb9d1SAndroid Build Coastguard Worker 
450*bbecb9d1SAndroid Build Coastguard Worker bool
render_context_main(const struct render_context_args * args)451*bbecb9d1SAndroid Build Coastguard Worker render_context_main(const struct render_context_args *args)
452*bbecb9d1SAndroid Build Coastguard Worker {
453*bbecb9d1SAndroid Build Coastguard Worker    struct render_context ctx;
454*bbecb9d1SAndroid Build Coastguard Worker 
455*bbecb9d1SAndroid Build Coastguard Worker    assert(args->valid && args->ctx_id && args->ctx_fd >= 0);
456*bbecb9d1SAndroid Build Coastguard Worker 
457*bbecb9d1SAndroid Build Coastguard Worker    if (!render_virgl_init(args->init_flags)) {
458*bbecb9d1SAndroid Build Coastguard Worker       close(args->ctx_fd);
459*bbecb9d1SAndroid Build Coastguard Worker       return false;
460*bbecb9d1SAndroid Build Coastguard Worker    }
461*bbecb9d1SAndroid Build Coastguard Worker 
462*bbecb9d1SAndroid Build Coastguard Worker    if (!render_context_init(&ctx, args)) {
463*bbecb9d1SAndroid Build Coastguard Worker       render_virgl_fini();
464*bbecb9d1SAndroid Build Coastguard Worker       close(args->ctx_fd);
465*bbecb9d1SAndroid Build Coastguard Worker       return false;
466*bbecb9d1SAndroid Build Coastguard Worker    }
467*bbecb9d1SAndroid Build Coastguard Worker 
468*bbecb9d1SAndroid Build Coastguard Worker    const bool ok = render_context_run(&ctx);
469*bbecb9d1SAndroid Build Coastguard Worker    render_context_fini(&ctx);
470*bbecb9d1SAndroid Build Coastguard Worker 
471*bbecb9d1SAndroid Build Coastguard Worker    render_virgl_fini();
472*bbecb9d1SAndroid Build Coastguard Worker 
473*bbecb9d1SAndroid Build Coastguard Worker    return ok;
474*bbecb9d1SAndroid Build Coastguard Worker }
475