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/BufferedBufImgOps.java
38918 views
1
/*
2
* Copyright (c) 2007, 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.color.ColorSpace;
29
import java.awt.image.AffineTransformOp;
30
import java.awt.image.BufferedImage;
31
import java.awt.image.BufferedImageOp;
32
import java.awt.image.BufferedImageOp;
33
import java.awt.image.ByteLookupTable;
34
import java.awt.image.ColorModel;
35
import java.awt.image.ConvolveOp;
36
import java.awt.image.IndexColorModel;
37
import java.awt.image.Kernel;
38
import java.awt.image.LookupOp;
39
import java.awt.image.LookupTable;
40
import java.awt.image.RescaleOp;
41
import java.awt.image.ShortLookupTable;
42
import sun.java2d.SurfaceData;
43
import sun.java2d.loops.CompositeType;
44
import static sun.java2d.pipe.BufferedOpCodes.*;
45
46
public class BufferedBufImgOps {
47
48
public static void enableBufImgOp(RenderQueue rq, SurfaceData srcData,
49
BufferedImage srcImg,
50
BufferedImageOp biop)
51
{
52
if (biop instanceof ConvolveOp) {
53
enableConvolveOp(rq, srcData, (ConvolveOp)biop);
54
} else if (biop instanceof RescaleOp) {
55
enableRescaleOp(rq, srcData, srcImg, (RescaleOp)biop);
56
} else if (biop instanceof LookupOp) {
57
enableLookupOp(rq, srcData, srcImg, (LookupOp)biop);
58
} else {
59
throw new InternalError("Unknown BufferedImageOp");
60
}
61
}
62
63
public static void disableBufImgOp(RenderQueue rq, BufferedImageOp biop) {
64
if (biop instanceof ConvolveOp) {
65
disableConvolveOp(rq);
66
} else if (biop instanceof RescaleOp) {
67
disableRescaleOp(rq);
68
} else if (biop instanceof LookupOp) {
69
disableLookupOp(rq);
70
} else {
71
throw new InternalError("Unknown BufferedImageOp");
72
}
73
}
74
75
/**************************** ConvolveOp support ****************************/
76
77
public static boolean isConvolveOpValid(ConvolveOp cop) {
78
Kernel kernel = cop.getKernel();
79
int kw = kernel.getWidth();
80
int kh = kernel.getHeight();
81
// REMIND: we currently can only handle 3x3 and 5x5 kernels,
82
// but hopefully this is just a temporary restriction;
83
// see native shader comments for more details
84
if (!(kw == 3 && kh == 3) && !(kw == 5 && kh == 5)) {
85
return false;
86
}
87
return true;
88
}
89
90
private static void enableConvolveOp(RenderQueue rq,
91
SurfaceData srcData,
92
ConvolveOp cop)
93
{
94
// assert rq.lock.isHeldByCurrentThread();
95
boolean edgeZero =
96
cop.getEdgeCondition() == ConvolveOp.EDGE_ZERO_FILL;
97
Kernel kernel = cop.getKernel();
98
int kernelWidth = kernel.getWidth();
99
int kernelHeight = kernel.getHeight();
100
int kernelSize = kernelWidth * kernelHeight;
101
int sizeofFloat = 4;
102
int totalBytesRequired = 4 + 8 + 12 + (kernelSize * sizeofFloat);
103
104
RenderBuffer buf = rq.getBuffer();
105
rq.ensureCapacityAndAlignment(totalBytesRequired, 4);
106
buf.putInt(ENABLE_CONVOLVE_OP);
107
buf.putLong(srcData.getNativeOps());
108
buf.putInt(edgeZero ? 1 : 0);
109
buf.putInt(kernelWidth);
110
buf.putInt(kernelHeight);
111
buf.put(kernel.getKernelData(null));
112
}
113
114
private static void disableConvolveOp(RenderQueue rq) {
115
// assert rq.lock.isHeldByCurrentThread();
116
RenderBuffer buf = rq.getBuffer();
117
rq.ensureCapacity(4);
118
buf.putInt(DISABLE_CONVOLVE_OP);
119
}
120
121
/**************************** RescaleOp support *****************************/
122
123
public static boolean isRescaleOpValid(RescaleOp rop,
124
BufferedImage srcImg)
125
{
126
int numFactors = rop.getNumFactors();
127
ColorModel srcCM = srcImg.getColorModel();
128
129
if (srcCM instanceof IndexColorModel) {
130
throw new
131
IllegalArgumentException("Rescaling cannot be "+
132
"performed on an indexed image");
133
}
134
if (numFactors != 1 &&
135
numFactors != srcCM.getNumColorComponents() &&
136
numFactors != srcCM.getNumComponents())
137
{
138
throw new IllegalArgumentException("Number of scaling constants "+
139
"does not equal the number of"+
140
" of color or color/alpha "+
141
" components");
142
}
143
144
int csType = srcCM.getColorSpace().getType();
145
if (csType != ColorSpace.TYPE_RGB &&
146
csType != ColorSpace.TYPE_GRAY)
147
{
148
// Not prepared to deal with other color spaces
149
return false;
150
}
151
152
if (numFactors == 2 || numFactors > 4) {
153
// Not really prepared to handle this at the native level, so...
154
return false;
155
}
156
157
return true;
158
}
159
160
private static void enableRescaleOp(RenderQueue rq,
161
SurfaceData srcData,
162
BufferedImage srcImg,
163
RescaleOp rop)
164
{
165
// assert rq.lock.isHeldByCurrentThread();
166
ColorModel srcCM = srcImg.getColorModel();
167
boolean nonPremult =
168
srcCM.hasAlpha() &&
169
srcCM.isAlphaPremultiplied();
170
171
/*
172
* Note: The user-provided scale factors and offsets are arranged
173
* in R/G/B/A order, regardless of the raw data order of the
174
* underlying Raster/DataBuffer. The source image data is ultimately
175
* converted into RGBA data when uploaded to an OpenGL texture
176
* (even for TYPE_GRAY), so the scale factors and offsets are already
177
* in the order expected by the native OpenGL code.
178
*
179
* However, the offsets provided by the user are in a range dictated
180
* by the size of each color/alpha band in the source image. For
181
* example, for 8/8/8 data each offset is in the range [0,255],
182
* for 5/5/5 data each offset is in the range [0,31], and so on.
183
* The OpenGL shader only thinks in terms of [0,1], so below we need
184
* to normalize the user-provided offset values into the range [0,1].
185
*/
186
int numFactors = rop.getNumFactors();
187
float[] origScaleFactors = rop.getScaleFactors(null);
188
float[] origOffsets = rop.getOffsets(null);
189
190
// To make things easier, we will always pass all four bands
191
// down to native code...
192
float[] normScaleFactors;
193
float[] normOffsets;
194
195
if (numFactors == 1) {
196
normScaleFactors = new float[4];
197
normOffsets = new float[4];
198
for (int i = 0; i < 3; i++) {
199
normScaleFactors[i] = origScaleFactors[0];
200
normOffsets[i] = origOffsets[0];
201
}
202
// Leave alpha untouched...
203
normScaleFactors[3] = 1.0f;
204
normOffsets[3] = 0.0f;
205
} else if (numFactors == 3) {
206
normScaleFactors = new float[4];
207
normOffsets = new float[4];
208
for (int i = 0; i < 3; i++) {
209
normScaleFactors[i] = origScaleFactors[i];
210
normOffsets[i] = origOffsets[i];
211
}
212
// Leave alpha untouched...
213
normScaleFactors[3] = 1.0f;
214
normOffsets[3] = 0.0f;
215
} else { // (numFactors == 4)
216
normScaleFactors = origScaleFactors;
217
normOffsets = origOffsets;
218
}
219
220
// The user-provided offsets are specified in the range
221
// of each source color band, but the OpenGL shader only wants
222
// to deal with data in the range [0,1], so we need to normalize
223
// each offset value to the range [0,1] here.
224
if (srcCM.getNumComponents() == 1) {
225
// Gray data
226
int nBits = srcCM.getComponentSize(0);
227
int maxValue = (1 << nBits) - 1;
228
for (int i = 0; i < 3; i++) {
229
normOffsets[i] /= maxValue;
230
}
231
} else {
232
// RGB(A) data
233
for (int i = 0; i < srcCM.getNumComponents(); i++) {
234
int nBits = srcCM.getComponentSize(i);
235
int maxValue = (1 << nBits) - 1;
236
normOffsets[i] /= maxValue;
237
}
238
}
239
240
int sizeofFloat = 4;
241
int totalBytesRequired = 4 + 8 + 4 + (4 * sizeofFloat * 2);
242
243
RenderBuffer buf = rq.getBuffer();
244
rq.ensureCapacityAndAlignment(totalBytesRequired, 4);
245
buf.putInt(ENABLE_RESCALE_OP);
246
buf.putLong(srcData.getNativeOps());
247
buf.putInt(nonPremult ? 1 : 0);
248
buf.put(normScaleFactors);
249
buf.put(normOffsets);
250
}
251
252
private static void disableRescaleOp(RenderQueue rq) {
253
// assert rq.lock.isHeldByCurrentThread();
254
RenderBuffer buf = rq.getBuffer();
255
rq.ensureCapacity(4);
256
buf.putInt(DISABLE_RESCALE_OP);
257
}
258
259
/**************************** LookupOp support ******************************/
260
261
public static boolean isLookupOpValid(LookupOp lop,
262
BufferedImage srcImg)
263
{
264
LookupTable table = lop.getTable();
265
int numComps = table.getNumComponents();
266
ColorModel srcCM = srcImg.getColorModel();
267
268
if (srcCM instanceof IndexColorModel) {
269
throw new
270
IllegalArgumentException("LookupOp cannot be "+
271
"performed on an indexed image");
272
}
273
if (numComps != 1 &&
274
numComps != srcCM.getNumComponents() &&
275
numComps != srcCM.getNumColorComponents())
276
{
277
throw new IllegalArgumentException("Number of arrays in the "+
278
" lookup table ("+
279
numComps+
280
") is not compatible with"+
281
" the src image: "+srcImg);
282
}
283
284
int csType = srcCM.getColorSpace().getType();
285
if (csType != ColorSpace.TYPE_RGB &&
286
csType != ColorSpace.TYPE_GRAY)
287
{
288
// Not prepared to deal with other color spaces
289
return false;
290
}
291
292
if (numComps == 2 || numComps > 4) {
293
// Not really prepared to handle this at the native level, so...
294
return false;
295
}
296
297
// The LookupTable spec says that "all arrays must be the
298
// same size" but unfortunately the constructors do not
299
// enforce that. Also, our native code only works with
300
// arrays no larger than 256 elements, so check both of
301
// these restrictions here.
302
if (table instanceof ByteLookupTable) {
303
byte[][] data = ((ByteLookupTable)table).getTable();
304
for (int i = 1; i < data.length; i++) {
305
if (data[i].length > 256 ||
306
data[i].length != data[i-1].length)
307
{
308
return false;
309
}
310
}
311
} else if (table instanceof ShortLookupTable) {
312
short[][] data = ((ShortLookupTable)table).getTable();
313
for (int i = 1; i < data.length; i++) {
314
if (data[i].length > 256 ||
315
data[i].length != data[i-1].length)
316
{
317
return false;
318
}
319
}
320
} else {
321
return false;
322
}
323
324
return true;
325
}
326
327
private static void enableLookupOp(RenderQueue rq,
328
SurfaceData srcData,
329
BufferedImage srcImg,
330
LookupOp lop)
331
{
332
// assert rq.lock.isHeldByCurrentThread();
333
boolean nonPremult =
334
srcImg.getColorModel().hasAlpha() &&
335
srcImg.isAlphaPremultiplied();
336
337
LookupTable table = lop.getTable();
338
int numBands = table.getNumComponents();
339
int offset = table.getOffset();
340
int bandLength;
341
int bytesPerElem;
342
boolean shortData;
343
344
if (table instanceof ShortLookupTable) {
345
short[][] data = ((ShortLookupTable)table).getTable();
346
bandLength = data[0].length;
347
bytesPerElem = 2;
348
shortData = true;
349
} else { // (table instanceof ByteLookupTable)
350
byte[][] data = ((ByteLookupTable)table).getTable();
351
bandLength = data[0].length;
352
bytesPerElem = 1;
353
shortData = false;
354
}
355
356
// Adjust the LUT length so that it ends on a 4-byte boundary
357
int totalLutBytes = numBands * bandLength * bytesPerElem;
358
int paddedLutBytes = (totalLutBytes + 3) & (~3);
359
int padding = paddedLutBytes - totalLutBytes;
360
int totalBytesRequired = 4 + 8 + 20 + paddedLutBytes;
361
362
RenderBuffer buf = rq.getBuffer();
363
rq.ensureCapacityAndAlignment(totalBytesRequired, 4);
364
buf.putInt(ENABLE_LOOKUP_OP);
365
buf.putLong(srcData.getNativeOps());
366
buf.putInt(nonPremult ? 1 : 0);
367
buf.putInt(shortData ? 1 : 0);
368
buf.putInt(numBands);
369
buf.putInt(bandLength);
370
buf.putInt(offset);
371
if (shortData) {
372
short[][] data = ((ShortLookupTable)table).getTable();
373
for (int i = 0; i < numBands; i++) {
374
buf.put(data[i]);
375
}
376
} else {
377
byte[][] data = ((ByteLookupTable)table).getTable();
378
for (int i = 0; i < numBands; i++) {
379
buf.put(data[i]);
380
}
381
}
382
if (padding != 0) {
383
buf.position(buf.position() + padding);
384
}
385
}
386
387
private static void disableLookupOp(RenderQueue rq) {
388
// assert rq.lock.isHeldByCurrentThread();
389
RenderBuffer buf = rq.getBuffer();
390
rq.ensureCapacity(4);
391
buf.putInt(DISABLE_LOOKUP_OP);
392
}
393
}
394
395