Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/vc4/vc4_fence.c
4570 views
1
/*
2
* Copyright © 2014 Broadcom
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 (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
13
* 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 NONINFRINGEMENT. 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 DEALINGS
21
* IN THE SOFTWARE.
22
*/
23
24
/** @file vc4_fence.c
25
*
26
* Seqno-based fence management.
27
*
28
* We have two mechanisms for waiting in our kernel API: You can wait on a BO
29
* to have all rendering to from any process to be completed, or wait on a
30
* seqno for that particular seqno to be passed. The fence API we're
31
* implementing is based on waiting for all rendering in the context to have
32
* completed (with no reference to what other processes might be doing with
33
* the same BOs), so we can just use the seqno of the last rendering we'd
34
* fired off as our fence marker.
35
*/
36
37
#include <libsync.h>
38
#include <fcntl.h>
39
40
#include "util/os_file.h"
41
#include "util/u_inlines.h"
42
43
#include "vc4_screen.h"
44
#include "vc4_context.h"
45
#include "vc4_bufmgr.h"
46
47
struct vc4_fence {
48
struct pipe_reference reference;
49
uint64_t seqno;
50
int fd;
51
};
52
53
static inline struct vc4_fence *
54
vc4_fence(struct pipe_fence_handle *pfence)
55
{
56
return (struct vc4_fence *)pfence;
57
}
58
59
static void
60
vc4_fence_reference(struct pipe_screen *pscreen,
61
struct pipe_fence_handle **pp,
62
struct pipe_fence_handle *pf)
63
{
64
struct vc4_fence **p = (struct vc4_fence **)pp;
65
struct vc4_fence *f = vc4_fence(pf);
66
struct vc4_fence *old = *p;
67
68
if (pipe_reference(&(*p)->reference, &f->reference)) {
69
if (old->fd >= 0)
70
close(old->fd);
71
free(old);
72
}
73
*p = f;
74
}
75
76
static bool
77
vc4_fence_finish(struct pipe_screen *pscreen,
78
struct pipe_context *ctx,
79
struct pipe_fence_handle *pf,
80
uint64_t timeout_ns)
81
{
82
struct vc4_screen *screen = vc4_screen(pscreen);
83
struct vc4_fence *f = vc4_fence(pf);
84
85
if (f->fd >= 0)
86
return sync_wait(f->fd, timeout_ns / 1000000) == 0;
87
88
return vc4_wait_seqno(screen, f->seqno, timeout_ns, "fence wait");
89
}
90
91
struct vc4_fence *
92
vc4_fence_create(struct vc4_screen *screen, uint64_t seqno, int fd)
93
{
94
struct vc4_fence *f = calloc(1, sizeof(*f));
95
96
if (!f)
97
return NULL;
98
99
pipe_reference_init(&f->reference, 1);
100
f->seqno = seqno;
101
f->fd = fd;
102
103
return f;
104
}
105
106
static void
107
vc4_fence_create_fd(struct pipe_context *pctx, struct pipe_fence_handle **pf,
108
int fd, enum pipe_fd_type type)
109
{
110
struct vc4_context *vc4 = vc4_context(pctx);
111
struct vc4_fence **fence = (struct vc4_fence **)pf;
112
113
assert(type == PIPE_FD_TYPE_NATIVE_SYNC);
114
*fence = vc4_fence_create(vc4->screen, vc4->last_emit_seqno,
115
os_dupfd_cloexec(fd));
116
}
117
118
static void
119
vc4_fence_server_sync(struct pipe_context *pctx,
120
struct pipe_fence_handle *pfence)
121
{
122
struct vc4_context *vc4 = vc4_context(pctx);
123
struct vc4_fence *fence = vc4_fence(pfence);
124
125
if (fence->fd >= 0)
126
sync_accumulate("vc4", &vc4->in_fence_fd, fence->fd);
127
}
128
129
static int
130
vc4_fence_get_fd(struct pipe_screen *screen, struct pipe_fence_handle *pfence)
131
{
132
struct vc4_fence *fence = vc4_fence(pfence);
133
134
return os_dupfd_cloexec(fence->fd);
135
}
136
137
int
138
vc4_fence_context_init(struct vc4_context *vc4)
139
{
140
vc4->base.create_fence_fd = vc4_fence_create_fd;
141
vc4->base.fence_server_sync = vc4_fence_server_sync;
142
vc4->in_fence_fd = -1;
143
144
/* Since we initialize the in_fence_fd to -1 (no wait necessary),
145
* we also need to initialize our in_syncobj as signaled.
146
*/
147
if (vc4->screen->has_syncobj) {
148
return drmSyncobjCreate(vc4->fd, DRM_SYNCOBJ_CREATE_SIGNALED,
149
&vc4->in_syncobj);
150
} else {
151
return 0;
152
}
153
}
154
155
void
156
vc4_fence_screen_init(struct vc4_screen *screen)
157
{
158
screen->base.fence_reference = vc4_fence_reference;
159
screen->base.fence_finish = vc4_fence_finish;
160
screen->base.fence_get_fd = vc4_fence_get_fd;
161
}
162
163