Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java
41159 views
1
/*
2
* Copyright (c) 2005, 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.opengl;
27
28
import sun.awt.util.ThreadGroupUtils;
29
import sun.java2d.pipe.RenderBuffer;
30
import sun.java2d.pipe.RenderQueue;
31
32
import static sun.java2d.pipe.BufferedOpCodes.*;
33
import java.security.AccessController;
34
import java.security.PrivilegedAction;
35
36
/**
37
* OGL-specific implementation of RenderQueue. This class provides a
38
* single (daemon) thread that is responsible for periodically flushing
39
* the queue, thus ensuring that only one thread communicates with the native
40
* OpenGL libraries for the entire process.
41
*/
42
public class OGLRenderQueue extends RenderQueue {
43
44
private static OGLRenderQueue theInstance;
45
private final QueueFlusher flusher;
46
47
@SuppressWarnings("removal")
48
private OGLRenderQueue() {
49
/*
50
* The thread must be a member of a thread group
51
* which will not get GCed before VM exit.
52
*/
53
flusher = AccessController.doPrivileged((PrivilegedAction<QueueFlusher>) QueueFlusher::new);
54
}
55
56
/**
57
* Returns the single OGLRenderQueue instance. If it has not yet been
58
* initialized, this method will first construct the single instance
59
* before returning it.
60
*/
61
public static synchronized OGLRenderQueue getInstance() {
62
if (theInstance == null) {
63
theInstance = new OGLRenderQueue();
64
}
65
return theInstance;
66
}
67
68
/**
69
* Flushes the single OGLRenderQueue instance synchronously. If an
70
* OGLRenderQueue has not yet been instantiated, this method is a no-op.
71
* This method is useful in the case of Toolkit.sync(), in which we want
72
* to flush the OGL pipeline, but only if the OGL pipeline is currently
73
* enabled. Since this class has few external dependencies, callers need
74
* not be concerned that calling this method will trigger initialization
75
* of the OGL pipeline and related classes.
76
*/
77
public static void sync() {
78
if (theInstance != null) {
79
theInstance.lock();
80
try {
81
theInstance.ensureCapacity(4);
82
theInstance.getBuffer().putInt(SYNC);
83
theInstance.flushNow();
84
} finally {
85
theInstance.unlock();
86
}
87
}
88
}
89
90
/**
91
* Disposes the native memory associated with the given native
92
* graphics config info pointer on the single queue flushing thread.
93
*/
94
public static void disposeGraphicsConfig(long pConfigInfo) {
95
OGLRenderQueue rq = getInstance();
96
rq.lock();
97
try {
98
// make sure we make the context associated with the given
99
// GraphicsConfig current before disposing the native resources
100
OGLContext.setScratchSurface(pConfigInfo);
101
102
RenderBuffer buf = rq.getBuffer();
103
rq.ensureCapacityAndAlignment(12, 4);
104
buf.putInt(DISPOSE_CONFIG);
105
buf.putLong(pConfigInfo);
106
107
// this call is expected to complete synchronously, so flush now
108
rq.flushNow();
109
} finally {
110
rq.unlock();
111
}
112
}
113
114
/**
115
* Returns true if the current thread is the OGL QueueFlusher thread.
116
*/
117
public static boolean isQueueFlusherThread() {
118
return (Thread.currentThread() == getInstance().flusher.thread);
119
}
120
121
public void flushNow() {
122
// assert lock.isHeldByCurrentThread();
123
try {
124
flusher.flushNow();
125
} catch (Exception e) {
126
System.err.println("exception in flushNow:");
127
e.printStackTrace();
128
}
129
}
130
131
public void flushAndInvokeNow(Runnable r) {
132
// assert lock.isHeldByCurrentThread();
133
try {
134
flusher.flushAndInvokeNow(r);
135
} catch (Exception e) {
136
System.err.println("exception in flushAndInvokeNow:");
137
e.printStackTrace();
138
}
139
}
140
141
private native void flushBuffer(long buf, int limit);
142
143
private void flushBuffer() {
144
// assert lock.isHeldByCurrentThread();
145
int limit = buf.position();
146
if (limit > 0) {
147
// process the queue
148
flushBuffer(buf.getAddress(), limit);
149
}
150
// reset the buffer position
151
buf.clear();
152
// clear the set of references, since we no longer need them
153
refSet.clear();
154
}
155
156
private class QueueFlusher implements Runnable {
157
private boolean needsFlush;
158
private Runnable task;
159
private Error error;
160
private final Thread thread;
161
162
public QueueFlusher() {
163
String name = "Java2D Queue Flusher";
164
thread = new Thread(ThreadGroupUtils.getRootThreadGroup(),
165
this, name, 0, false);
166
thread.setDaemon(true);
167
thread.setPriority(Thread.MAX_PRIORITY);
168
thread.start();
169
}
170
171
public synchronized void flushNow() {
172
// wake up the flusher
173
needsFlush = true;
174
notify();
175
176
// wait for flush to complete
177
while (needsFlush) {
178
try {
179
wait();
180
} catch (InterruptedException e) {
181
}
182
}
183
184
// re-throw any error that may have occurred during the flush
185
if (error != null) {
186
throw error;
187
}
188
}
189
190
public synchronized void flushAndInvokeNow(Runnable task) {
191
this.task = task;
192
flushNow();
193
}
194
195
public synchronized void run() {
196
boolean timedOut = false;
197
while (true) {
198
while (!needsFlush) {
199
try {
200
timedOut = false;
201
/*
202
* Wait until we're woken up with a flushNow() call,
203
* or the timeout period elapses (so that we can
204
* flush the queue periodically).
205
*/
206
wait(100);
207
/*
208
* We will automatically flush the queue if the
209
* following conditions apply:
210
* - the wait() timed out
211
* - we can lock the queue (without blocking)
212
* - there is something in the queue to flush
213
* Otherwise, just continue (we'll flush eventually).
214
*/
215
if (!needsFlush && (timedOut = tryLock())) {
216
if (buf.position() > 0) {
217
needsFlush = true;
218
} else {
219
unlock();
220
}
221
}
222
} catch (InterruptedException e) {
223
}
224
}
225
try {
226
// reset the throwable state
227
error = null;
228
// flush the buffer now
229
flushBuffer();
230
// if there's a task, invoke that now as well
231
if (task != null) {
232
task.run();
233
}
234
} catch (Error e) {
235
error = e;
236
} catch (Exception x) {
237
System.err.println("exception in QueueFlusher:");
238
x.printStackTrace();
239
} finally {
240
if (timedOut) {
241
unlock();
242
}
243
task = null;
244
// allow the waiting thread to continue
245
needsFlush = false;
246
notify();
247
}
248
}
249
}
250
}
251
}
252
253