3977af8078ef65d37e9a49a8e988b466cfa12cb2
[mesa.git] / src / gallium / drivers / lima / lima_submit.c
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, sublicense,
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 shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 */
23
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "xf86drm.h"
28 #include "libsync.h"
29 #include "drm-uapi/lima_drm.h"
30
31 #include "util/ralloc.h"
32 #include "util/u_dynarray.h"
33 #include "util/os_time.h"
34
35 #include "lima_screen.h"
36 #include "lima_context.h"
37 #include "lima_submit.h"
38 #include "lima_bo.h"
39 #include "lima_util.h"
40
41 struct lima_submit {
42 struct lima_screen *screen;
43 uint32_t pipe;
44 uint32_t ctx;
45
46 int in_sync_fd;
47 uint32_t in_sync;
48 uint32_t out_sync;
49
50 struct util_dynarray gem_bos;
51 struct util_dynarray bos;
52 };
53
54
55 #define VOID2U64(x) ((uint64_t)(unsigned long)(x))
56
57 struct lima_submit *lima_submit_create(struct lima_context *ctx, uint32_t pipe)
58 {
59 struct lima_submit *s;
60
61 s = rzalloc(ctx, struct lima_submit);
62 if (!s)
63 return NULL;
64
65 s->screen = lima_screen(ctx->base.screen);
66 s->pipe = pipe;
67 s->ctx = ctx->id;
68 s->in_sync_fd = -1;
69
70 int err = drmSyncobjCreate(s->screen->fd, DRM_SYNCOBJ_CREATE_SIGNALED,
71 &s->out_sync);
72 if (err)
73 goto err_out0;
74
75 err = drmSyncobjCreate(s->screen->fd, DRM_SYNCOBJ_CREATE_SIGNALED,
76 &s->in_sync);
77 if (err)
78 goto err_out1;
79
80 util_dynarray_init(&s->gem_bos, s);
81
82 return s;
83
84 err_out1:
85 drmSyncobjDestroy(s->screen->fd, s->out_sync);
86 err_out0:
87 ralloc_free(s);
88 return NULL;
89 }
90
91 void lima_submit_free(struct lima_submit *submit)
92 {
93 if (submit->in_sync_fd >= 0)
94 close(submit->in_sync_fd);
95 drmSyncobjDestroy(submit->screen->fd, submit->in_sync);
96 drmSyncobjDestroy(submit->screen->fd, submit->out_sync);
97 }
98
99 bool lima_submit_add_bo(struct lima_submit *submit, struct lima_bo *bo, uint32_t flags)
100 {
101 util_dynarray_foreach(&submit->gem_bos, struct drm_lima_gem_submit_bo, gem_bo) {
102 if (bo->handle == gem_bo->handle) {
103 gem_bo->flags |= flags;
104 return true;
105 }
106 }
107
108 struct drm_lima_gem_submit_bo *submit_bo =
109 util_dynarray_grow(&submit->gem_bos, struct drm_lima_gem_submit_bo, 1);
110 submit_bo->handle = bo->handle;
111 submit_bo->flags = flags;
112
113 struct lima_bo **jbo = util_dynarray_grow(&submit->bos, struct lima_bo *, 1);
114 *jbo = bo;
115
116 /* prevent bo from being freed when submit start */
117 lima_bo_reference(bo);
118
119 return true;
120 }
121
122 bool lima_submit_start(struct lima_submit *submit, void *frame, uint32_t size)
123 {
124 struct drm_lima_gem_submit req = {
125 .ctx = submit->ctx,
126 .pipe = submit->pipe,
127 .nr_bos = submit->gem_bos.size / sizeof(struct drm_lima_gem_submit_bo),
128 .bos = VOID2U64(util_dynarray_begin(&submit->gem_bos)),
129 .frame = VOID2U64(frame),
130 .frame_size = size,
131 .out_sync = submit->out_sync,
132 };
133
134 if (submit->in_sync_fd >= 0) {
135 int err = drmSyncobjImportSyncFile(submit->screen->fd, submit->in_sync,
136 submit->in_sync_fd);
137 if (err)
138 return false;
139
140 req.in_sync[0] = submit->in_sync;
141 close(submit->in_sync_fd);
142 submit->in_sync_fd = -1;
143 }
144
145 bool ret = drmIoctl(submit->screen->fd, DRM_IOCTL_LIMA_GEM_SUBMIT, &req) == 0;
146
147 util_dynarray_foreach(&submit->bos, struct lima_bo *, bo) {
148 lima_bo_free(*bo);
149 }
150
151 util_dynarray_clear(&submit->gem_bos);
152 util_dynarray_clear(&submit->bos);
153 return ret;
154 }
155
156 bool lima_submit_wait(struct lima_submit *submit, uint64_t timeout_ns)
157 {
158 int64_t abs_timeout = os_time_get_absolute_timeout(timeout_ns);
159 if (abs_timeout == OS_TIMEOUT_INFINITE)
160 abs_timeout = INT64_MAX;
161
162 return !drmSyncobjWait(submit->screen->fd, &submit->out_sync, 1, abs_timeout, 0, NULL);
163 }
164
165 bool lima_submit_has_bo(struct lima_submit *submit, struct lima_bo *bo, bool all)
166 {
167 util_dynarray_foreach(&submit->gem_bos, struct drm_lima_gem_submit_bo, gem_bo) {
168 if (bo->handle == gem_bo->handle) {
169 if (all)
170 return true;
171 else
172 return gem_bo->flags & LIMA_SUBMIT_BO_WRITE;
173 }
174 }
175
176 return false;
177 }
178
179 bool lima_submit_add_in_sync(struct lima_submit *submit, int fd)
180 {
181 return !sync_accumulate("lima", &submit->in_sync_fd, fd);
182 }
183
184 bool lima_submit_get_out_sync(struct lima_submit *submit, int *fd)
185 {
186 return !drmSyncobjExportSyncFile(submit->screen->fd, submit->out_sync, fd);
187 }