Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/macosx/classes/sun/java2d/metal/MTLRenderQueue.java
41159 views
1
/*
2
* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.java2d.metal;
27
28
import sun.awt.util.ThreadGroupUtils;
29
import sun.java2d.pipe.RenderBuffer;
30
import sun.java2d.pipe.RenderQueue;
31
32
import java.security.AccessController;
33
import java.security.PrivilegedAction;
34
35
import static sun.java2d.pipe.BufferedOpCodes.DISPOSE_CONFIG;
36
import static sun.java2d.pipe.BufferedOpCodes.SYNC;
37
38
/**
39
* MTL-specific implementation of RenderQueue. This class provides a
40
* single (daemon) thread that is responsible for periodically flushing
41
* the queue, thus ensuring that only one thread communicates with the native
42
* OpenGL libraries for the entire process.
43
*/
44
public class MTLRenderQueue extends RenderQueue {
45
46
private static MTLRenderQueue theInstance;
47
private final QueueFlusher flusher;
48
49
@SuppressWarnings("removal")
50
private MTLRenderQueue() {
51
/*
52
* The thread must be a member of a thread group
53
* which will not get GCed before VM exit.
54
*/
55
flusher = AccessController.doPrivileged((PrivilegedAction<QueueFlusher>) QueueFlusher::new);
56
}
57
58
/**
59
* Returns the single MTLRenderQueue instance. If it has not yet been
60
* initialized, this method will first construct the single instance
61
* before returning it.
62
*/
63
public static synchronized MTLRenderQueue getInstance() {
64
if (theInstance == null) {
65
theInstance = new MTLRenderQueue();
66
}
67
return theInstance;
68
}
69
70
/**
71
* Flushes the single MTLRenderQueue instance synchronously. If an
72
* MTLRenderQueue has not yet been instantiated, this method is a no-op.
73
* This method is useful in the case of Toolkit.sync(), in which we want
74
* to flush the MTL pipeline, but only if the MTL pipeline is currently
75
* enabled. Since this class has few external dependencies, callers need
76
* not be concerned that calling this method will trigger initialization
77
* of the MTL pipeline and related classes.
78
*/
79
public static void sync() {
80
if (theInstance != null) {
81
theInstance.lock();
82
try {
83
theInstance.ensureCapacity(4);
84
theInstance.getBuffer().putInt(SYNC);
85
theInstance.flushNow();
86
} finally {
87
theInstance.unlock();
88
}
89
}
90
}
91
92
/**
93
* Disposes the native memory associated with the given native
94
* graphics config info pointer on the single queue flushing thread.
95
*/
96
public static void disposeGraphicsConfig(long pConfigInfo) {
97
MTLRenderQueue rq = getInstance();
98
rq.lock();
99
try {
100
// make sure we make the context associated with the given
101
// GraphicsConfig current before disposing the native resources
102
MTLContext.setScratchSurface(pConfigInfo);
103
104
RenderBuffer buf = rq.getBuffer();
105
rq.ensureCapacityAndAlignment(12, 4);
106
buf.putInt(DISPOSE_CONFIG);
107
buf.putLong(pConfigInfo);
108
109
// this call is expected to complete synchronously, so flush now
110
rq.flushNow();
111
} finally {
112
rq.unlock();
113
}
114
}
115
116
/**
117
* Returns true if the current thread is the MTL QueueFlusher thread.
118
*/
119
public static boolean isQueueFlusherThread() {
120
return (Thread.currentThread() == getInstance().flusher.thread);
121
}
122
123
124
@Override
125
public void flushNow() {
126
// assert lock.isHeldByCurrentThread();
127
try {
128
flusher.flushNow();
129
} catch (Exception e) {
130
System.err.println("exception in flushNow:");
131
e.printStackTrace();
132
}
133
}
134
135
public void flushAndInvokeNow(Runnable r) {
136
// assert lock.isHeldByCurrentThread();
137
try {
138
flusher.flushAndInvokeNow(r);
139
} catch (Exception e) {
140
System.err.println("exception in flushAndInvokeNow:");
141
e.printStackTrace();
142
}
143
}
144
145
private native void flushBuffer(long buf, int limit);
146
147
private void flushBuffer() {
148
// assert lock.isHeldByCurrentThread();
149
int limit = buf.position();
150
if (limit > 0) {
151
// process the queue
152
flushBuffer(buf.getAddress(), limit);
153
}
154
// reset the buffer position
155
buf.clear();
156
// clear the set of references, since we no longer need them
157
refSet.clear();
158
}
159
160
private class QueueFlusher implements Runnable {
161
private boolean needsFlush;
162
private Runnable task;
163
private Error error;
164
private final Thread thread;
165
166
public QueueFlusher() {
167
String name = "Java2D Queue Flusher";
168
thread = new Thread(ThreadGroupUtils.getRootThreadGroup(),
169
this, name, 0, false);
170
thread.setDaemon(true);
171
thread.setPriority(Thread.MAX_PRIORITY);
172
thread.start();
173
}
174
175
public synchronized void flushNow() {
176
// wake up the flusher
177
needsFlush = true;
178
notify();
179
180
// wait for flush to complete
181
while (needsFlush) {
182
try {
183
wait();
184
} catch (InterruptedException e) {
185
}
186
}
187
188
// re-throw any error that may have occurred during the flush
189
if (error != null) {
190
throw error;
191
}
192
}
193
194
public synchronized void flushAndInvokeNow(Runnable task) {
195
this.task = task;
196
flushNow();
197
}
198
199
public synchronized void run() {
200
boolean timedOut = false;
201
while (true) {
202
while (!needsFlush) {
203
try {
204
timedOut = false;
205
/*
206
* Wait until we're woken up with a flushNow() call,
207
* or the timeout period elapses (so that we can
208
* flush the queue periodically).
209
*/
210
wait(100);
211
/*
212
* We will automatically flush the queue if the
213
* following conditions apply:
214
* - the wait() timed out
215
* - we can lock the queue (without blocking)
216
* - there is something in the queue to flush
217
* Otherwise, just continue (we'll flush eventually).
218
*/
219
if (!needsFlush && (timedOut = tryLock())) {
220
if (buf.position() > 0) {
221
needsFlush = true;
222
} else {
223
unlock();
224
}
225
}
226
} catch (InterruptedException e) {
227
}
228
}
229
try {
230
// reset the throwable state
231
error = null;
232
// flush the buffer now
233
flushBuffer();
234
// if there's a task, invoke that now as well
235
if (task != null) {
236
task.run();
237
}
238
} catch (Error e) {
239
error = e;
240
} catch (Exception x) {
241
System.err.println("exception in QueueFlusher:");
242
x.printStackTrace();
243
} finally {
244
if (timedOut) {
245
unlock();
246
}
247
task = null;
248
// allow the waiting thread to continue
249
needsFlush = false;
250
notify();
251
}
252
}
253
}
254
}
255
}
256
257