iris: Expose aux buffer as 2nd plane w/modifiers
[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 };
132
133 if (submit->in_sync_fd >= 0) {
134 int err = drmSyncobjImportSyncFile(submit->screen->fd, submit->in_sync,
135 submit->in_sync_fd);
136 if (err)
137 return false;
138
139 req.in_sync[0] = submit->in_sync;
140 close(submit->in_sync_fd);
141 submit->in_sync_fd = -1;
142 }
143
144 bool ret = drmIoctl(submit->screen->fd, DRM_IOCTL_LIMA_GEM_SUBMIT, &req) == 0;
145
146 util_dynarray_foreach(&submit->bos, struct lima_bo *, bo) {
147 lima_bo_free(*bo);
148 }
149
150 util_dynarray_clear(&submit->gem_bos);
151 util_dynarray_clear(&submit->bos);
152 return ret;
153 }
154
155 bool lima_submit_wait(struct lima_submit *submit, uint64_t timeout_ns)
156 {
157 int64_t abs_timeout = os_time_get_absolute_timeout(timeout_ns);
158
159 return !drmSyncobjWait(submit->screen->fd, &submit->out_sync, 1, abs_timeout, 0, NULL);
160 }
161
162 bool lima_submit_has_bo(struct lima_submit *submit, struct lima_bo *bo, bool all)
163 {
164 util_dynarray_foreach(&submit->gem_bos, struct drm_lima_gem_submit_bo, gem_bo) {
165 if (bo->handle == gem_bo->handle) {
166 if (all)
167 return true;
168 else
169 return gem_bo->flags & LIMA_SUBMIT_BO_WRITE;
170 }
171 }
172
173 return false;
174 }
175
176 bool lima_submit_add_in_sync(struct lima_submit *submit, int fd)
177 {
178 return !sync_accumulate("lima", &submit->in_sync_fd, fd);
179 }
180
181 bool lima_submit_get_out_sync(struct lima_submit *submit, int *fd)
182 {
183 return !drmSyncobjExportSyncFile(submit->screen->fd, submit->out_sync, fd);
184 }