Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/java2d/pipe/BufferedContext.java
38918 views
1
/*
2
* Copyright (c) 2005, 2016, 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.awt.AlphaComposite;
29
import java.awt.Color;
30
import java.awt.Composite;
31
import java.awt.Paint;
32
import java.awt.geom.AffineTransform;
33
import sun.java2d.pipe.hw.AccelSurface;
34
import sun.java2d.InvalidPipeException;
35
import sun.java2d.SunGraphics2D;
36
import sun.java2d.loops.XORComposite;
37
import static sun.java2d.pipe.BufferedOpCodes.*;
38
import static sun.java2d.pipe.BufferedRenderPipe.BYTES_PER_SPAN;
39
40
import java.lang.annotation.Native;
41
import java.lang.ref.Reference;
42
import java.lang.ref.WeakReference;
43
44
/**
45
* Base context class for managing state in a single-threaded rendering
46
* environment. Each state-setting operation (e.g. SET_COLOR) is added to
47
* the provided RenderQueue, which will be processed at a later time by a
48
* single thread. Note that the RenderQueue lock must be acquired before
49
* calling the validate() method (or any other method in this class). See
50
* the RenderQueue class comments for a sample usage scenario.
51
*
52
* @see RenderQueue
53
*/
54
public abstract class BufferedContext {
55
56
/*
57
* The following flags help the internals of validate() determine
58
* the appropriate (meaning correct, or optimal) code path when
59
* setting up the current context. The flags can be bitwise OR'd
60
* together as needed.
61
*/
62
63
/**
64
* Indicates that no flags are needed; take all default code paths.
65
*/
66
@Native public static final int NO_CONTEXT_FLAGS = (0 << 0);
67
/**
68
* Indicates that the source surface (or color value, if it is a simple
69
* rendering operation) is opaque (has an alpha value of 1.0). If this
70
* flag is present, it allows us to disable blending in certain
71
* situations in order to improve performance.
72
*/
73
@Native public static final int SRC_IS_OPAQUE = (1 << 0);
74
/**
75
* Indicates that the operation uses an alpha mask, which may determine
76
* the code path that is used when setting up the current paint state.
77
*/
78
@Native public static final int USE_MASK = (1 << 1);
79
80
protected RenderQueue rq;
81
protected RenderBuffer buf;
82
83
/**
84
* This is a reference to the most recently validated BufferedContext. If
85
* this value is null, it means that there is no current context. It is
86
* provided here so that validate() only needs to do a quick reference
87
* check to see if the BufferedContext passed to that method is the same
88
* as the one we've cached here.
89
*/
90
protected static BufferedContext currentContext;
91
92
private Reference<AccelSurface> validSrcDataRef = new WeakReference<>(null);
93
private Reference<AccelSurface> validDstDataRef = new WeakReference<>(null);
94
private Reference<Region> validClipRef = new WeakReference<>(null);
95
private Reference<Composite> validCompRef = new WeakReference<>(null);
96
private Reference<Paint> validPaintRef = new WeakReference<>(null);
97
// renamed from isValidatedPaintAColor as part of a work around for 6764257
98
private boolean isValidatedPaintJustAColor;
99
private int validatedRGB;
100
private int validatedFlags;
101
private boolean xformInUse;
102
private AffineTransform transform;
103
104
protected BufferedContext(RenderQueue rq) {
105
this.rq = rq;
106
this.buf = rq.getBuffer();
107
}
108
109
/**
110
* Fetches the BufferedContextContext associated with the dst. surface
111
* and validates the context using the given parameters. Most rendering
112
* operations will call this method first in order to set the necessary
113
* state before issuing rendering commands.
114
*
115
* Note: must be called while the RenderQueue lock is held.
116
*
117
* It's assumed that the type of surfaces has been checked by the Renderer
118
*
119
* @throws InvalidPipeException if either src or dest surface is not valid
120
* or lost
121
* @see RenderQueue#lock
122
* @see RenderQueue#unlock
123
*/
124
public static void validateContext(AccelSurface srcData,
125
AccelSurface dstData,
126
Region clip, Composite comp,
127
AffineTransform xform,
128
Paint paint, SunGraphics2D sg2d,
129
int flags)
130
{
131
// assert rq.lock.isHeldByCurrentThread();
132
BufferedContext context = dstData.getContext();
133
context.validate(srcData, dstData,
134
clip, comp, xform, paint, sg2d, flags);
135
}
136
137
/**
138
* Fetches the BufferedContextassociated with the surface
139
* and disables all context state settings.
140
*
141
* Note: must be called while the RenderQueue lock is held.
142
*
143
* It's assumed that the type of surfaces has been checked by the Renderer
144
*
145
* @throws InvalidPipeException if the surface is not valid
146
* or lost
147
* @see RenderQueue#lock
148
* @see RenderQueue#unlock
149
*/
150
public static void validateContext(AccelSurface surface) {
151
// assert rt.lock.isHeldByCurrentThread();
152
validateContext(surface, surface,
153
null, null, null, null, null, NO_CONTEXT_FLAGS);
154
}
155
156
/**
157
* Validates the given parameters against the current state for this
158
* context. If this context is not current, it will be made current
159
* for the given source and destination surfaces, and the viewport will
160
* be updated. Then each part of the context state (clip, composite,
161
* etc.) is checked against the previous value. If the value has changed
162
* since the last call to validate(), it will be updated accordingly.
163
*
164
* Note that the SunGraphics2D parameter is only used for the purposes
165
* of validating a (non-null) Paint parameter. In all other cases it
166
* is safe to pass a null SunGraphics2D and it will be ignored.
167
*
168
* Note: must be called while the RenderQueue lock is held.
169
*
170
* It's assumed that the type of surfaces has been checked by the Renderer
171
*
172
* @throws InvalidPipeException if either src or dest surface is not valid
173
* or lost
174
*/
175
public void validate(AccelSurface srcData, AccelSurface dstData,
176
Region clip, Composite comp,
177
AffineTransform xform,
178
Paint paint, SunGraphics2D sg2d, int flags)
179
{
180
// assert rq.lock.isHeldByCurrentThread();
181
182
boolean updateClip = false;
183
boolean updatePaint = false;
184
185
if (!dstData.isValid() ||
186
dstData.isSurfaceLost() || srcData.isSurfaceLost())
187
{
188
invalidateContext();
189
throw new InvalidPipeException("bounds changed or surface lost");
190
}
191
192
if (paint instanceof Color) {
193
// REMIND: not 30-bit friendly
194
int newRGB = ((Color)paint).getRGB();
195
if (isValidatedPaintJustAColor) {
196
if (newRGB != validatedRGB) {
197
validatedRGB = newRGB;
198
updatePaint = true;
199
}
200
} else {
201
validatedRGB = newRGB;
202
updatePaint = true;
203
isValidatedPaintJustAColor = true;
204
}
205
} else if (validPaintRef.get() != paint) {
206
updatePaint = true;
207
// this should be set when we are switching from paint to color
208
// in which case this condition will be true
209
isValidatedPaintJustAColor = false;
210
}
211
212
final AccelSurface validatedSrcData = validSrcDataRef.get();
213
final AccelSurface validatedDstData = validDstDataRef.get();
214
if ((currentContext != this) ||
215
(srcData != validatedSrcData) ||
216
(dstData != validatedDstData))
217
{
218
if (dstData != validatedDstData) {
219
// the clip is dependent on the destination surface, so we
220
// need to update it if we have a new destination surface
221
updateClip = true;
222
}
223
224
if (paint == null) {
225
// make sure we update the color state (otherwise, it might
226
// not be updated if this is the first time the context
227
// is being validated)
228
updatePaint = true;
229
}
230
231
// update the current source and destination surfaces
232
setSurfaces(srcData, dstData);
233
234
currentContext = this;
235
validSrcDataRef = new WeakReference<>(srcData);
236
validDstDataRef = new WeakReference<>(dstData);
237
}
238
239
// validate clip
240
final Region validatedClip = validClipRef.get();
241
if ((clip != validatedClip) || updateClip) {
242
if (clip != null) {
243
if (updateClip ||
244
validatedClip == null ||
245
!(validatedClip.isRectangular() && clip.isRectangular()) ||
246
((clip.getLoX() != validatedClip.getLoX() ||
247
clip.getLoY() != validatedClip.getLoY() ||
248
clip.getHiX() != validatedClip.getHiX() ||
249
clip.getHiY() != validatedClip.getHiY())))
250
{
251
setClip(clip);
252
}
253
} else {
254
resetClip();
255
}
256
validClipRef = new WeakReference<>(clip);
257
}
258
259
// validate composite (note that a change in the context flags
260
// may require us to update the composite state, even if the
261
// composite has not changed)
262
if ((comp != validCompRef.get()) || (flags != validatedFlags)) {
263
if (comp != null) {
264
setComposite(comp, flags);
265
} else {
266
resetComposite();
267
}
268
// the paint state is dependent on the composite state, so make
269
// sure we update the color below
270
updatePaint = true;
271
validCompRef = new WeakReference<>(comp);
272
validatedFlags = flags;
273
}
274
275
// validate transform
276
boolean txChanged = false;
277
if (xform == null) {
278
if (xformInUse) {
279
resetTransform();
280
xformInUse = false;
281
txChanged = true;
282
} else if (sg2d != null && !sg2d.transform.equals(transform)) {
283
txChanged = true;
284
}
285
if (sg2d != null && txChanged) {
286
transform = new AffineTransform(sg2d.transform);
287
}
288
} else {
289
setTransform(xform);
290
xformInUse = true;
291
txChanged = true;
292
}
293
// non-Color paints may require paint revalidation
294
if (!isValidatedPaintJustAColor && txChanged) {
295
updatePaint = true;
296
}
297
298
// validate paint
299
if (updatePaint) {
300
if (paint != null) {
301
BufferedPaints.setPaint(rq, sg2d, paint, flags);
302
} else {
303
BufferedPaints.resetPaint(rq);
304
}
305
validPaintRef = new WeakReference<>(paint);
306
}
307
308
// mark dstData dirty
309
// REMIND: is this really needed now? we do it in SunGraphics2D..
310
dstData.markDirty();
311
}
312
313
/**
314
* Invalidates the surfaces associated with this context. This is
315
* useful when the context is no longer needed, and we want to break
316
* the chain caused by these surface references.
317
*
318
* Note: must be called while the RenderQueue lock is held.
319
*
320
* @see RenderQueue#lock
321
* @see RenderQueue#unlock
322
*/
323
private void invalidateSurfaces() {
324
validSrcDataRef.clear();
325
validDstDataRef.clear();
326
}
327
328
private void setSurfaces(AccelSurface srcData,
329
AccelSurface dstData)
330
{
331
// assert rq.lock.isHeldByCurrentThread();
332
rq.ensureCapacityAndAlignment(20, 4);
333
buf.putInt(SET_SURFACES);
334
buf.putLong(srcData.getNativeOps());
335
buf.putLong(dstData.getNativeOps());
336
}
337
338
private void resetClip() {
339
// assert rq.lock.isHeldByCurrentThread();
340
rq.ensureCapacity(4);
341
buf.putInt(RESET_CLIP);
342
}
343
344
private void setClip(Region clip) {
345
// assert rq.lock.isHeldByCurrentThread();
346
if (clip.isRectangular()) {
347
rq.ensureCapacity(20);
348
buf.putInt(SET_RECT_CLIP);
349
buf.putInt(clip.getLoX()).putInt(clip.getLoY());
350
buf.putInt(clip.getHiX()).putInt(clip.getHiY());
351
} else {
352
rq.ensureCapacity(28); // so that we have room for at least a span
353
buf.putInt(BEGIN_SHAPE_CLIP);
354
buf.putInt(SET_SHAPE_CLIP_SPANS);
355
// include a placeholder for the span count
356
int countIndex = buf.position();
357
buf.putInt(0);
358
int spanCount = 0;
359
int remainingSpans = buf.remaining() / BYTES_PER_SPAN;
360
int span[] = new int[4];
361
SpanIterator si = clip.getSpanIterator();
362
while (si.nextSpan(span)) {
363
if (remainingSpans == 0) {
364
buf.putInt(countIndex, spanCount);
365
rq.flushNow();
366
buf.putInt(SET_SHAPE_CLIP_SPANS);
367
countIndex = buf.position();
368
buf.putInt(0);
369
spanCount = 0;
370
remainingSpans = buf.remaining() / BYTES_PER_SPAN;
371
}
372
buf.putInt(span[0]); // x1
373
buf.putInt(span[1]); // y1
374
buf.putInt(span[2]); // x2
375
buf.putInt(span[3]); // y2
376
spanCount++;
377
remainingSpans--;
378
}
379
buf.putInt(countIndex, spanCount);
380
rq.ensureCapacity(4);
381
buf.putInt(END_SHAPE_CLIP);
382
}
383
}
384
385
private void resetComposite() {
386
// assert rq.lock.isHeldByCurrentThread();
387
rq.ensureCapacity(4);
388
buf.putInt(RESET_COMPOSITE);
389
}
390
391
private void setComposite(Composite comp, int flags) {
392
// assert rq.lock.isHeldByCurrentThread();
393
if (comp instanceof AlphaComposite) {
394
AlphaComposite ac = (AlphaComposite)comp;
395
rq.ensureCapacity(16);
396
buf.putInt(SET_ALPHA_COMPOSITE);
397
buf.putInt(ac.getRule());
398
buf.putFloat(ac.getAlpha());
399
buf.putInt(flags);
400
} else if (comp instanceof XORComposite) {
401
int xorPixel = ((XORComposite)comp).getXorPixel();
402
rq.ensureCapacity(8);
403
buf.putInt(SET_XOR_COMPOSITE);
404
buf.putInt(xorPixel);
405
} else {
406
throw new InternalError("not yet implemented");
407
}
408
}
409
410
private void resetTransform() {
411
// assert rq.lock.isHeldByCurrentThread();
412
rq.ensureCapacity(4);
413
buf.putInt(RESET_TRANSFORM);
414
}
415
416
private void setTransform(AffineTransform xform) {
417
// assert rq.lock.isHeldByCurrentThread();
418
rq.ensureCapacityAndAlignment(52, 4);
419
buf.putInt(SET_TRANSFORM);
420
buf.putDouble(xform.getScaleX());
421
buf.putDouble(xform.getShearY());
422
buf.putDouble(xform.getShearX());
423
buf.putDouble(xform.getScaleY());
424
buf.putDouble(xform.getTranslateX());
425
buf.putDouble(xform.getTranslateY());
426
}
427
428
/**
429
* Resets this context's surfaces and all attributes.
430
*
431
* Note: must be called while the RenderQueue lock is held.
432
*
433
* @see RenderQueue#lock
434
* @see RenderQueue#unlock
435
*/
436
public void invalidateContext() {
437
resetTransform();
438
resetComposite();
439
resetClip();
440
BufferedPaints.resetPaint(rq);
441
invalidateSurfaces();
442
validCompRef.clear();
443
validClipRef.clear();
444
validPaintRef.clear();
445
isValidatedPaintJustAColor = false;
446
xformInUse = false;
447
}
448
449
/**
450
* Returns a singleton {@code RenderQueue} object used by the rendering
451
* pipeline.
452
*
453
* @return a render queue
454
* @see RenderQueue
455
*/
456
public abstract RenderQueue getRenderQueue();
457
458
/**
459
* Saves the the state of this context.
460
* It may reset the current context.
461
*
462
* Note: must be called while the RenderQueue lock is held.
463
*
464
* @see RenderQueue#lock
465
* @see RenderQueue#unlock
466
*/
467
public abstract void saveState();
468
469
/**
470
* Restores the native state of this context.
471
* It may reset the current context.
472
*
473
* Note: must be called while the RenderQueue lock is held.
474
*
475
* @see RenderQueue#lock
476
* @see RenderQueue#unlock
477
*/
478
public abstract void restoreState();
479
}
480
481