Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/freedreno/drm/freedreno_pipe.c
4564 views
1
/*
2
* Copyright (C) 2012-2018 Rob Clark <[email protected]>
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 FROM,
20
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
* SOFTWARE.
22
*
23
* Authors:
24
* Rob Clark <[email protected]>
25
*/
26
27
#include "freedreno_drmif.h"
28
#include "freedreno_priv.h"
29
30
/**
31
* priority of zero is highest priority, and higher numeric values are
32
* lower priorities
33
*/
34
struct fd_pipe *
35
fd_pipe_new2(struct fd_device *dev, enum fd_pipe_id id, uint32_t prio)
36
{
37
struct fd_pipe *pipe;
38
uint64_t val;
39
40
if (id > FD_PIPE_MAX) {
41
ERROR_MSG("invalid pipe id: %d", id);
42
return NULL;
43
}
44
45
if ((prio != 1) && (fd_device_version(dev) < FD_VERSION_SUBMIT_QUEUES)) {
46
ERROR_MSG("invalid priority!");
47
return NULL;
48
}
49
50
pipe = dev->funcs->pipe_new(dev, id, prio);
51
if (!pipe) {
52
ERROR_MSG("allocation failed");
53
return NULL;
54
}
55
56
pipe->dev = fd_device_ref(dev);
57
pipe->id = id;
58
p_atomic_set(&pipe->refcnt, 1);
59
60
fd_pipe_get_param(pipe, FD_GPU_ID, &val);
61
pipe->gpu_id = val;
62
63
pipe->control_mem = fd_bo_new(dev, sizeof(*pipe->control),
64
0, "pipe-control");
65
pipe->control = fd_bo_map(pipe->control_mem);
66
67
/* We could be getting a bo from the bo-cache, make sure the fence value
68
* is not garbage:
69
*/
70
pipe->control->fence = 0;
71
72
/* We don't want the control_mem bo to hold a reference to the ourself,
73
* so disable userspace fencing. This also means that we won't be able
74
* to determine if the buffer is idle which is needed by bo-cache. But
75
* pipe creation/destroy is not a high frequency event so just disable
76
* the bo-cache as well:
77
*/
78
pipe->control_mem->nosync = true;
79
pipe->control_mem->bo_reuse = NO_CACHE;
80
81
return pipe;
82
}
83
84
struct fd_pipe *
85
fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id)
86
{
87
return fd_pipe_new2(dev, id, 1);
88
}
89
90
struct fd_pipe *
91
fd_pipe_ref(struct fd_pipe *pipe)
92
{
93
simple_mtx_lock(&table_lock);
94
fd_pipe_ref_locked(pipe);
95
simple_mtx_unlock(&table_lock);
96
return pipe;
97
}
98
99
struct fd_pipe *
100
fd_pipe_ref_locked(struct fd_pipe *pipe)
101
{
102
simple_mtx_assert_locked(&table_lock);
103
pipe->refcnt++;
104
return pipe;
105
}
106
107
void
108
fd_pipe_del(struct fd_pipe *pipe)
109
{
110
simple_mtx_lock(&table_lock);
111
fd_pipe_del_locked(pipe);
112
simple_mtx_unlock(&table_lock);
113
}
114
115
void
116
fd_pipe_del_locked(struct fd_pipe *pipe)
117
{
118
simple_mtx_assert_locked(&table_lock);
119
if (!p_atomic_dec_zero(&pipe->refcnt))
120
return;
121
fd_bo_del_locked(pipe->control_mem);
122
fd_device_del_locked(pipe->dev);
123
pipe->funcs->destroy(pipe);
124
}
125
126
/**
127
* Discard any unflushed deferred submits. This is called at context-
128
* destroy to make sure we don't leak unflushed submits.
129
*/
130
void
131
fd_pipe_purge(struct fd_pipe *pipe)
132
{
133
struct fd_device *dev = pipe->dev;
134
struct list_head deferred_submits;
135
136
list_inithead(&deferred_submits);
137
138
simple_mtx_lock(&dev->submit_lock);
139
140
foreach_submit_safe (deferred_submit, &dev->deferred_submits) {
141
if (deferred_submit->pipe != pipe)
142
continue;
143
144
list_del(&deferred_submit->node);
145
list_addtail(&deferred_submit->node, &deferred_submits);
146
dev->deferred_cmds -= fd_ringbuffer_cmd_count(deferred_submit->primary);
147
}
148
149
simple_mtx_unlock(&dev->submit_lock);
150
151
foreach_submit_safe (deferred_submit, &deferred_submits) {
152
list_del(&deferred_submit->node);
153
fd_submit_del(deferred_submit);
154
}
155
}
156
157
int
158
fd_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param, uint64_t *value)
159
{
160
return pipe->funcs->get_param(pipe, param, value);
161
}
162
163
int
164
fd_pipe_wait(struct fd_pipe *pipe, const struct fd_fence *fence)
165
{
166
return fd_pipe_wait_timeout(pipe, fence, ~0);
167
}
168
169
int
170
fd_pipe_wait_timeout(struct fd_pipe *pipe, const struct fd_fence *fence,
171
uint64_t timeout)
172
{
173
if (!fd_fence_after(fence->ufence, pipe->control->fence))
174
return 0;
175
176
fd_pipe_flush(pipe, fence->ufence);
177
178
return pipe->funcs->wait(pipe, fence, timeout);
179
}
180
181
uint32_t
182
fd_pipe_emit_fence(struct fd_pipe *pipe, struct fd_ringbuffer *ring)
183
{
184
uint32_t fence = ++pipe->last_fence;
185
186
if (pipe->gpu_id >= 500) {
187
OUT_PKT7(ring, CP_EVENT_WRITE, 4);
188
OUT_RING(ring, CP_EVENT_WRITE_0_EVENT(CACHE_FLUSH_TS));
189
OUT_RELOC(ring, control_ptr(pipe, fence)); /* ADDR_LO/HI */
190
OUT_RING(ring, fence);
191
} else {
192
OUT_PKT3(ring, CP_EVENT_WRITE, 3);
193
OUT_RING(ring, CP_EVENT_WRITE_0_EVENT(CACHE_FLUSH_TS));
194
OUT_RELOC(ring, control_ptr(pipe, fence)); /* ADDR */
195
OUT_RING(ring, fence);
196
}
197
198
return fence;
199
}
200
201