Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/sun/java2d/pipe/RenderQueue.java
41159 views
1
/*
2
* Copyright (c) 2005, 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.pipe;
27
28
import java.util.HashSet;
29
import java.util.Set;
30
import sun.awt.SunToolkit;
31
32
/**
33
* The RenderQueue class encapsulates a RenderBuffer on which rendering
34
* operations are enqueued. Note that the RenderQueue lock must be acquired
35
* before performing any operations on the queue (e.g. enqueuing an operation
36
* or flushing the queue). A sample usage scenario follows:
37
*
38
* public void drawSomething(...) {
39
* rq.lock();
40
* try {
41
* ctx.validate(...);
42
* rq.ensureCapacity(4);
43
* rq.getBuffer().putInt(DRAW_SOMETHING);
44
* ...
45
* } finally {
46
* rq.unlock();
47
* }
48
* }
49
*
50
* If you are enqueuing an operation that involves 8-byte parameters (i.e.
51
* long or double values), it is imperative that you ensure proper
52
* alignment of the underlying RenderBuffer. This can be accomplished
53
* simply by providing an offset to the first 8-byte parameter in your
54
* operation to the ensureCapacityAndAlignment() method. For example:
55
*
56
* public void drawStuff(...) {
57
* rq.lock();
58
* try {
59
* RenderBuffer buf = rq.getBuffer();
60
* ctx.validate(...);
61
* // 28 total bytes in the operation, 12 bytes to the first long
62
* rq.ensureCapacityAndAlignment(28, 12);
63
* buf.putInt(DRAW_STUFF);
64
* buf.putInt(x).putInt(y);
65
* buf.putLong(addr1);
66
* buf.putLong(addr2);
67
* } finally {
68
* rq.unlock();
69
* }
70
* }
71
*/
72
public abstract class RenderQueue {
73
74
/** The size of the underlying buffer, in bytes. */
75
private static final int BUFFER_SIZE = 32000;
76
77
/** The underlying buffer for this queue. */
78
protected RenderBuffer buf;
79
80
/**
81
* A Set containing hard references to Objects that must stay alive until
82
* the queue has been completely flushed.
83
*/
84
protected Set<Object> refSet;
85
86
protected RenderQueue() {
87
refSet = new HashSet<>();
88
buf = RenderBuffer.allocate(BUFFER_SIZE);
89
}
90
91
/**
92
* Locks the queue for read/write access.
93
*/
94
public final void lock() {
95
/*
96
* Implementation note: In theory we should have two separate locks:
97
* one lock to synchronize access to the RenderQueue, and then a
98
* separate lock (the AWT lock) that only needs to be acquired when
99
* we are about to flush the queue (using native windowing system
100
* operations). In practice it has been difficult to enforce the
101
* correct lock ordering; sometimes AWT will have already acquired
102
* the AWT lock before grabbing the RQ lock (see 6253009), while the
103
* expected order should be RQ lock and then AWT lock. Due to this
104
* issue, using two separate locks is prone to deadlocks. Therefore,
105
* to solve this issue we have decided to eliminate the separate RQ
106
* lock and instead just acquire the AWT lock here. (Someday it might
107
* be nice to go back to the old two-lock system, but that would
108
* require potentially risky changes to AWT to ensure that it never
109
* acquires the AWT lock before calling into 2D code that wants to
110
* acquire the RQ lock.)
111
*/
112
SunToolkit.awtLock();
113
}
114
115
/**
116
* Attempts to lock the queue. If successful, this method returns true,
117
* indicating that the caller is responsible for calling
118
* {@code unlock}; otherwise this method returns false.
119
*/
120
public final boolean tryLock() {
121
return SunToolkit.awtTryLock();
122
}
123
124
/**
125
* Unlocks the queue.
126
*/
127
public final void unlock() {
128
SunToolkit.awtUnlock();
129
}
130
131
/**
132
* Adds the given Object to the set of hard references, which will
133
* prevent that Object from being disposed until the queue has been
134
* flushed completely. This is useful in cases where some enqueued
135
* data could become invalid if the reference Object were garbage
136
* collected before the queue could be processed. (For example, keeping
137
* a hard reference to a FontStrike will prevent any enqueued glyph
138
* images associated with that strike from becoming invalid before the
139
* queue is flushed.) The reference set will be cleared immediately
140
* after the queue is flushed each time.
141
*/
142
public final void addReference(Object ref) {
143
refSet.add(ref);
144
}
145
146
/**
147
* Returns the encapsulated RenderBuffer object.
148
*/
149
public final RenderBuffer getBuffer() {
150
return buf;
151
}
152
153
/**
154
* Ensures that there will be enough room on the underlying buffer
155
* for the following operation. If the operation will not fit given
156
* the remaining space, the buffer will be flushed immediately, leaving
157
* an empty buffer for the impending operation.
158
*
159
* @param opsize size (in bytes) of the following operation
160
*/
161
public final void ensureCapacity(int opsize) {
162
if (buf.remaining() < opsize) {
163
flushNow();
164
}
165
}
166
167
/**
168
* Convenience method that is equivalent to calling ensureCapacity()
169
* followed by ensureAlignment(). The ensureCapacity() call allows for an
170
* extra 4 bytes of space in case the ensureAlignment() method needs to
171
* insert a NOOP token on the buffer.
172
*
173
* @param opsize size (in bytes) of the following operation
174
* @param first8ByteValueOffset offset (in bytes) from the current
175
* position to the first 8-byte value used in the following operation
176
*/
177
public final void ensureCapacityAndAlignment(int opsize,
178
int first8ByteValueOffset)
179
{
180
ensureCapacity(opsize + 4);
181
ensureAlignment(first8ByteValueOffset);
182
}
183
184
/**
185
* Inserts a 4-byte NOOP token when necessary to ensure that all 8-byte
186
* parameters for the following operation are added to the underlying
187
* buffer with an 8-byte memory alignment.
188
*
189
* @param first8ByteValueOffset offset (in bytes) from the current
190
* position to the first 8-byte value used in the following operation
191
*/
192
public final void ensureAlignment(int first8ByteValueOffset) {
193
int first8ByteValuePosition = buf.position() + first8ByteValueOffset;
194
if ((first8ByteValuePosition & 7) != 0) {
195
buf.putInt(BufferedOpCodes.NOOP);
196
}
197
}
198
199
/**
200
* Immediately processes each operation currently pending on the buffer.
201
* This method will block until the entire buffer has been flushed. The
202
* queue lock must be acquired before calling this method.
203
*/
204
public abstract void flushNow();
205
206
/**
207
* Immediately processes each operation currently pending on the buffer,
208
* and then invokes the provided task. This method will block until the
209
* entire buffer has been flushed and the provided task has been executed.
210
* The queue lock must be acquired before calling this method.
211
*/
212
public abstract void flushAndInvokeNow(Runnable task);
213
214
/**
215
* Updates the current position of the underlying buffer, and then
216
* flushes the queue immediately. This method is useful when native code
217
* has added data to the queue and needs to flush immediately.
218
*/
219
public void flushNow(int position) {
220
buf.position(position);
221
flushNow();
222
}
223
}
224
225