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