Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/java2d/pipe/BufferedBufImgOps.java
38918 views
/*1* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.java2d.pipe;2627import java.awt.color.ColorSpace;28import java.awt.image.AffineTransformOp;29import java.awt.image.BufferedImage;30import java.awt.image.BufferedImageOp;31import java.awt.image.BufferedImageOp;32import java.awt.image.ByteLookupTable;33import java.awt.image.ColorModel;34import java.awt.image.ConvolveOp;35import java.awt.image.IndexColorModel;36import java.awt.image.Kernel;37import java.awt.image.LookupOp;38import java.awt.image.LookupTable;39import java.awt.image.RescaleOp;40import java.awt.image.ShortLookupTable;41import sun.java2d.SurfaceData;42import sun.java2d.loops.CompositeType;43import static sun.java2d.pipe.BufferedOpCodes.*;4445public class BufferedBufImgOps {4647public static void enableBufImgOp(RenderQueue rq, SurfaceData srcData,48BufferedImage srcImg,49BufferedImageOp biop)50{51if (biop instanceof ConvolveOp) {52enableConvolveOp(rq, srcData, (ConvolveOp)biop);53} else if (biop instanceof RescaleOp) {54enableRescaleOp(rq, srcData, srcImg, (RescaleOp)biop);55} else if (biop instanceof LookupOp) {56enableLookupOp(rq, srcData, srcImg, (LookupOp)biop);57} else {58throw new InternalError("Unknown BufferedImageOp");59}60}6162public static void disableBufImgOp(RenderQueue rq, BufferedImageOp biop) {63if (biop instanceof ConvolveOp) {64disableConvolveOp(rq);65} else if (biop instanceof RescaleOp) {66disableRescaleOp(rq);67} else if (biop instanceof LookupOp) {68disableLookupOp(rq);69} else {70throw new InternalError("Unknown BufferedImageOp");71}72}7374/**************************** ConvolveOp support ****************************/7576public static boolean isConvolveOpValid(ConvolveOp cop) {77Kernel kernel = cop.getKernel();78int kw = kernel.getWidth();79int kh = kernel.getHeight();80// REMIND: we currently can only handle 3x3 and 5x5 kernels,81// but hopefully this is just a temporary restriction;82// see native shader comments for more details83if (!(kw == 3 && kh == 3) && !(kw == 5 && kh == 5)) {84return false;85}86return true;87}8889private static void enableConvolveOp(RenderQueue rq,90SurfaceData srcData,91ConvolveOp cop)92{93// assert rq.lock.isHeldByCurrentThread();94boolean edgeZero =95cop.getEdgeCondition() == ConvolveOp.EDGE_ZERO_FILL;96Kernel kernel = cop.getKernel();97int kernelWidth = kernel.getWidth();98int kernelHeight = kernel.getHeight();99int kernelSize = kernelWidth * kernelHeight;100int sizeofFloat = 4;101int totalBytesRequired = 4 + 8 + 12 + (kernelSize * sizeofFloat);102103RenderBuffer buf = rq.getBuffer();104rq.ensureCapacityAndAlignment(totalBytesRequired, 4);105buf.putInt(ENABLE_CONVOLVE_OP);106buf.putLong(srcData.getNativeOps());107buf.putInt(edgeZero ? 1 : 0);108buf.putInt(kernelWidth);109buf.putInt(kernelHeight);110buf.put(kernel.getKernelData(null));111}112113private static void disableConvolveOp(RenderQueue rq) {114// assert rq.lock.isHeldByCurrentThread();115RenderBuffer buf = rq.getBuffer();116rq.ensureCapacity(4);117buf.putInt(DISABLE_CONVOLVE_OP);118}119120/**************************** RescaleOp support *****************************/121122public static boolean isRescaleOpValid(RescaleOp rop,123BufferedImage srcImg)124{125int numFactors = rop.getNumFactors();126ColorModel srcCM = srcImg.getColorModel();127128if (srcCM instanceof IndexColorModel) {129throw new130IllegalArgumentException("Rescaling cannot be "+131"performed on an indexed image");132}133if (numFactors != 1 &&134numFactors != srcCM.getNumColorComponents() &&135numFactors != srcCM.getNumComponents())136{137throw new IllegalArgumentException("Number of scaling constants "+138"does not equal the number of"+139" of color or color/alpha "+140" components");141}142143int csType = srcCM.getColorSpace().getType();144if (csType != ColorSpace.TYPE_RGB &&145csType != ColorSpace.TYPE_GRAY)146{147// Not prepared to deal with other color spaces148return false;149}150151if (numFactors == 2 || numFactors > 4) {152// Not really prepared to handle this at the native level, so...153return false;154}155156return true;157}158159private static void enableRescaleOp(RenderQueue rq,160SurfaceData srcData,161BufferedImage srcImg,162RescaleOp rop)163{164// assert rq.lock.isHeldByCurrentThread();165ColorModel srcCM = srcImg.getColorModel();166boolean nonPremult =167srcCM.hasAlpha() &&168srcCM.isAlphaPremultiplied();169170/*171* Note: The user-provided scale factors and offsets are arranged172* in R/G/B/A order, regardless of the raw data order of the173* underlying Raster/DataBuffer. The source image data is ultimately174* converted into RGBA data when uploaded to an OpenGL texture175* (even for TYPE_GRAY), so the scale factors and offsets are already176* in the order expected by the native OpenGL code.177*178* However, the offsets provided by the user are in a range dictated179* by the size of each color/alpha band in the source image. For180* example, for 8/8/8 data each offset is in the range [0,255],181* for 5/5/5 data each offset is in the range [0,31], and so on.182* The OpenGL shader only thinks in terms of [0,1], so below we need183* to normalize the user-provided offset values into the range [0,1].184*/185int numFactors = rop.getNumFactors();186float[] origScaleFactors = rop.getScaleFactors(null);187float[] origOffsets = rop.getOffsets(null);188189// To make things easier, we will always pass all four bands190// down to native code...191float[] normScaleFactors;192float[] normOffsets;193194if (numFactors == 1) {195normScaleFactors = new float[4];196normOffsets = new float[4];197for (int i = 0; i < 3; i++) {198normScaleFactors[i] = origScaleFactors[0];199normOffsets[i] = origOffsets[0];200}201// Leave alpha untouched...202normScaleFactors[3] = 1.0f;203normOffsets[3] = 0.0f;204} else if (numFactors == 3) {205normScaleFactors = new float[4];206normOffsets = new float[4];207for (int i = 0; i < 3; i++) {208normScaleFactors[i] = origScaleFactors[i];209normOffsets[i] = origOffsets[i];210}211// Leave alpha untouched...212normScaleFactors[3] = 1.0f;213normOffsets[3] = 0.0f;214} else { // (numFactors == 4)215normScaleFactors = origScaleFactors;216normOffsets = origOffsets;217}218219// The user-provided offsets are specified in the range220// of each source color band, but the OpenGL shader only wants221// to deal with data in the range [0,1], so we need to normalize222// each offset value to the range [0,1] here.223if (srcCM.getNumComponents() == 1) {224// Gray data225int nBits = srcCM.getComponentSize(0);226int maxValue = (1 << nBits) - 1;227for (int i = 0; i < 3; i++) {228normOffsets[i] /= maxValue;229}230} else {231// RGB(A) data232for (int i = 0; i < srcCM.getNumComponents(); i++) {233int nBits = srcCM.getComponentSize(i);234int maxValue = (1 << nBits) - 1;235normOffsets[i] /= maxValue;236}237}238239int sizeofFloat = 4;240int totalBytesRequired = 4 + 8 + 4 + (4 * sizeofFloat * 2);241242RenderBuffer buf = rq.getBuffer();243rq.ensureCapacityAndAlignment(totalBytesRequired, 4);244buf.putInt(ENABLE_RESCALE_OP);245buf.putLong(srcData.getNativeOps());246buf.putInt(nonPremult ? 1 : 0);247buf.put(normScaleFactors);248buf.put(normOffsets);249}250251private static void disableRescaleOp(RenderQueue rq) {252// assert rq.lock.isHeldByCurrentThread();253RenderBuffer buf = rq.getBuffer();254rq.ensureCapacity(4);255buf.putInt(DISABLE_RESCALE_OP);256}257258/**************************** LookupOp support ******************************/259260public static boolean isLookupOpValid(LookupOp lop,261BufferedImage srcImg)262{263LookupTable table = lop.getTable();264int numComps = table.getNumComponents();265ColorModel srcCM = srcImg.getColorModel();266267if (srcCM instanceof IndexColorModel) {268throw new269IllegalArgumentException("LookupOp cannot be "+270"performed on an indexed image");271}272if (numComps != 1 &&273numComps != srcCM.getNumComponents() &&274numComps != srcCM.getNumColorComponents())275{276throw new IllegalArgumentException("Number of arrays in the "+277" lookup table ("+278numComps+279") is not compatible with"+280" the src image: "+srcImg);281}282283int csType = srcCM.getColorSpace().getType();284if (csType != ColorSpace.TYPE_RGB &&285csType != ColorSpace.TYPE_GRAY)286{287// Not prepared to deal with other color spaces288return false;289}290291if (numComps == 2 || numComps > 4) {292// Not really prepared to handle this at the native level, so...293return false;294}295296// The LookupTable spec says that "all arrays must be the297// same size" but unfortunately the constructors do not298// enforce that. Also, our native code only works with299// arrays no larger than 256 elements, so check both of300// these restrictions here.301if (table instanceof ByteLookupTable) {302byte[][] data = ((ByteLookupTable)table).getTable();303for (int i = 1; i < data.length; i++) {304if (data[i].length > 256 ||305data[i].length != data[i-1].length)306{307return false;308}309}310} else if (table instanceof ShortLookupTable) {311short[][] data = ((ShortLookupTable)table).getTable();312for (int i = 1; i < data.length; i++) {313if (data[i].length > 256 ||314data[i].length != data[i-1].length)315{316return false;317}318}319} else {320return false;321}322323return true;324}325326private static void enableLookupOp(RenderQueue rq,327SurfaceData srcData,328BufferedImage srcImg,329LookupOp lop)330{331// assert rq.lock.isHeldByCurrentThread();332boolean nonPremult =333srcImg.getColorModel().hasAlpha() &&334srcImg.isAlphaPremultiplied();335336LookupTable table = lop.getTable();337int numBands = table.getNumComponents();338int offset = table.getOffset();339int bandLength;340int bytesPerElem;341boolean shortData;342343if (table instanceof ShortLookupTable) {344short[][] data = ((ShortLookupTable)table).getTable();345bandLength = data[0].length;346bytesPerElem = 2;347shortData = true;348} else { // (table instanceof ByteLookupTable)349byte[][] data = ((ByteLookupTable)table).getTable();350bandLength = data[0].length;351bytesPerElem = 1;352shortData = false;353}354355// Adjust the LUT length so that it ends on a 4-byte boundary356int totalLutBytes = numBands * bandLength * bytesPerElem;357int paddedLutBytes = (totalLutBytes + 3) & (~3);358int padding = paddedLutBytes - totalLutBytes;359int totalBytesRequired = 4 + 8 + 20 + paddedLutBytes;360361RenderBuffer buf = rq.getBuffer();362rq.ensureCapacityAndAlignment(totalBytesRequired, 4);363buf.putInt(ENABLE_LOOKUP_OP);364buf.putLong(srcData.getNativeOps());365buf.putInt(nonPremult ? 1 : 0);366buf.putInt(shortData ? 1 : 0);367buf.putInt(numBands);368buf.putInt(bandLength);369buf.putInt(offset);370if (shortData) {371short[][] data = ((ShortLookupTable)table).getTable();372for (int i = 0; i < numBands; i++) {373buf.put(data[i]);374}375} else {376byte[][] data = ((ByteLookupTable)table).getTable();377for (int i = 0; i < numBands; i++) {378buf.put(data[i]);379}380}381if (padding != 0) {382buf.position(buf.position() + padding);383}384}385386private static void disableLookupOp(RenderQueue rq) {387// assert rq.lock.isHeldByCurrentThread();388RenderBuffer buf = rq.getBuffer();389rq.ensureCapacity(4);390buf.putInt(DISABLE_LOOKUP_OP);391}392}393394395