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