Path: blob/master/src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java
41159 views
/*1* Copyright (c) 2019, 2021, 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*/24package sun.java2d.metal;2526import sun.java2d.SunGraphics2D;27import sun.java2d.SurfaceData;28import sun.java2d.loops.CompositeType;2930import java.awt.LinearGradientPaint;31import java.awt.MultipleGradientPaint;32import java.awt.TexturePaint;3334import java.awt.MultipleGradientPaint.ColorSpaceType;35import java.awt.MultipleGradientPaint.CycleMethod;36import java.awt.image.BufferedImage;37import java.util.HashMap;38import java.util.Map;3940import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_GRAD_SHADER;41import static sun.java2d.pipe.BufferedPaints.MULTI_MAX_FRACTIONS;4243abstract class MTLPaints {4445/**46* Holds all registered implementations, using the corresponding47* SunGraphics2D.PAINT_* constant as the hash key.48*/49private static Map<Integer, MTLPaints> impls =50new HashMap<Integer, MTLPaints>(4, 1.0f);5152static {53impls.put(SunGraphics2D.PAINT_GRADIENT, new Gradient());54impls.put(SunGraphics2D.PAINT_LIN_GRADIENT, new LinearGradient());55impls.put(SunGraphics2D.PAINT_RAD_GRADIENT, new RadialGradient());56impls.put(SunGraphics2D.PAINT_TEXTURE, new Texture());57}5859/**60* Attempts to locate an implementation corresponding to the paint state61* of the provided SunGraphics2D object. If no implementation can be62* found, or if the paint cannot be accelerated under the conditions63* of the SunGraphics2D, this method returns false; otherwise, returns64* true.65*/66static boolean isValid(SunGraphics2D sg2d) {67MTLPaints impl = impls.get(sg2d.paintState);68return (impl != null && impl.isPaintValid(sg2d));69}7071/**72* Returns true if this implementation is able to accelerate the73* Paint object associated with, and under the conditions of, the74* provided SunGraphics2D instance; otherwise returns false.75*/76abstract boolean isPaintValid(SunGraphics2D sg2d);7778/************************* GradientPaint support ****************************/7980private static class Gradient extends MTLPaints {81private Gradient() {}8283/**84* There are no restrictions for accelerating GradientPaint, so85* this method always returns true.86*/87@Override88boolean isPaintValid(SunGraphics2D sg2d) {89return true;90}91}9293/************************** TexturePaint support ****************************/9495private static class Texture extends MTLPaints {96private Texture() {}9798/**99* Returns true if the given TexturePaint instance can be used by the100* accelerated MTLPaints.Texture implementation. A TexturePaint is101* considered valid if the following conditions are met:102* - the texture image dimensions are power-of-two103* - the texture image can be (or is already) cached in an Metal104* texture object105*/106@Override107boolean isPaintValid(SunGraphics2D sg2d) {108TexturePaint paint = (TexturePaint)sg2d.paint;109MTLSurfaceData dstData = (MTLSurfaceData)sg2d.surfaceData;110BufferedImage bi = paint.getImage();111112SurfaceData srcData =113dstData.getSourceSurfaceData(bi,114SunGraphics2D.TRANSFORM_ISIDENT,115CompositeType.SrcOver, null);116if (!(srcData instanceof MTLSurfaceData)) {117// REMIND: this is a hack that attempts to cache the system118// memory image from the TexturePaint instance into an119// Metal texture...120srcData =121dstData.getSourceSurfaceData(bi,122SunGraphics2D.TRANSFORM_ISIDENT,123CompositeType.SrcOver, null);124if (!(srcData instanceof MTLSurfaceData)) {125return false;126}127}128129// verify that the source surface is actually a texture130MTLSurfaceData mtlData = (MTLSurfaceData)srcData;131if (mtlData.getType() != MTLSurfaceData.TEXTURE) {132return false;133}134135return true;136}137}138139/****************** Shared MultipleGradientPaint support ********************/140141private abstract static class MultiGradient extends MTLPaints {142protected MultiGradient() {}143144/**145* Returns true if the given MultipleGradientPaint instance can be146* used by the accelerated MTLPaints.MultiGradient implementation.147* A MultipleGradientPaint is considered valid if the following148* conditions are met:149* - the number of gradient "stops" is <= MAX_FRACTIONS150* - the destination has support for fragment shaders151*/152@Override153boolean isPaintValid(SunGraphics2D sg2d) {154MultipleGradientPaint paint = (MultipleGradientPaint)sg2d.paint;155// REMIND: ugh, this creates garbage; would be nicer if156// we had a MultipleGradientPaint.getNumStops() method...157if (paint.getFractions().length > MULTI_MAX_FRACTIONS) {158return false;159}160161MTLSurfaceData dstData = (MTLSurfaceData)sg2d.surfaceData;162MTLGraphicsConfig gc = dstData.getMTLGraphicsConfig();163if (!gc.isCapPresent(CAPS_EXT_GRAD_SHADER)) {164return false;165}166167return true;168}169}170171/********************** LinearGradientPaint support *************************/172173private static class LinearGradient extends MultiGradient {174private LinearGradient() {}175176@Override177boolean isPaintValid(SunGraphics2D sg2d) {178LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint;179180if (paint.getFractions().length == 2 &&181paint.getCycleMethod() != CycleMethod.REPEAT &&182paint.getColorSpace() != ColorSpaceType.LINEAR_RGB)183{184// we can delegate to the optimized two-color gradient185// codepath, which does not require fragment shader support186return true;187}188189return super.isPaintValid(sg2d);190}191}192193/********************** RadialGradientPaint support *************************/194195private static class RadialGradient extends MultiGradient {196private RadialGradient() {}197}198}199200201