src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java
branchmetal-prototype-branch
changeset 57416 e153174dba06
equal deleted inserted replaced
57400:978ffc56771f 57416:e153174dba06
       
     1 /*
       
     2  * Copyright (c) 2019, 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 package sun.java2d.metal;
       
    26 
       
    27 import sun.java2d.SunGraphics2D;
       
    28 import sun.java2d.SurfaceData;
       
    29 import sun.java2d.loops.CompositeType;
       
    30 
       
    31 import java.awt.*;
       
    32 import java.awt.MultipleGradientPaint.ColorSpaceType;
       
    33 import java.awt.MultipleGradientPaint.CycleMethod;
       
    34 import java.awt.image.BufferedImage;
       
    35 import java.util.HashMap;
       
    36 import java.util.Map;
       
    37 
       
    38 import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_GRAD_SHADER;
       
    39 import static sun.java2d.pipe.BufferedPaints.MULTI_MAX_FRACTIONS;
       
    40 
       
    41 abstract class MTLPaints {
       
    42 
       
    43     /**
       
    44      * Holds all registered implementations, using the corresponding
       
    45      * SunGraphics2D.PAINT_* constant as the hash key.
       
    46      */
       
    47     private static Map<Integer, MTLPaints> impls =
       
    48             new HashMap<Integer, MTLPaints>(4, 1.0f);
       
    49 
       
    50     static {
       
    51         impls.put(SunGraphics2D.PAINT_GRADIENT, new Gradient());
       
    52         impls.put(SunGraphics2D.PAINT_LIN_GRADIENT, new LinearGradient());
       
    53         impls.put(SunGraphics2D.PAINT_RAD_GRADIENT, new RadialGradient());
       
    54         impls.put(SunGraphics2D.PAINT_TEXTURE, new Texture());
       
    55     }
       
    56 
       
    57     /**
       
    58      * Attempts to locate an implementation corresponding to the paint state
       
    59      * of the provided SunGraphics2D object.  If no implementation can be
       
    60      * found, or if the paint cannot be accelerated under the conditions
       
    61      * of the SunGraphics2D, this method returns false; otherwise, returns
       
    62      * true.
       
    63      */
       
    64     static boolean isValid(SunGraphics2D sg2d) {
       
    65         MTLPaints impl = impls.get(sg2d.paintState);
       
    66         return (impl != null && impl.isPaintValid(sg2d));
       
    67     }
       
    68 
       
    69     /**
       
    70      * Returns true if this implementation is able to accelerate the
       
    71      * Paint object associated with, and under the conditions of, the
       
    72      * provided SunGraphics2D instance; otherwise returns false.
       
    73      */
       
    74     abstract boolean isPaintValid(SunGraphics2D sg2d);
       
    75 
       
    76     /************************* GradientPaint support ****************************/
       
    77 
       
    78     private static class Gradient extends MTLPaints {
       
    79         private Gradient() {}
       
    80 
       
    81         /**
       
    82          * There are no restrictions for accelerating GradientPaint, so
       
    83          * this method always returns true.
       
    84          */
       
    85         @Override
       
    86         boolean isPaintValid(SunGraphics2D sg2d) {
       
    87             return true;
       
    88         }
       
    89     }
       
    90 
       
    91     /************************** TexturePaint support ****************************/
       
    92 
       
    93     private static class Texture extends MTLPaints {
       
    94         private Texture() {}
       
    95 
       
    96         /**
       
    97          * Returns true if the given TexturePaint instance can be used by the
       
    98          * accelerated MTLPaints.Texture implementation.  A TexturePaint is
       
    99          * considered valid if the following conditions are met:
       
   100          *   - the texture image dimensions are power-of-two (or the
       
   101          *     GL_ARB_texture_non_power_of_two extension is present)
       
   102          *   - the texture image can be (or is already) cached in an OpenGL
       
   103          *     texture object
       
   104          */
       
   105         @Override
       
   106         boolean isPaintValid(SunGraphics2D sg2d) {
       
   107             TexturePaint paint = (TexturePaint)sg2d.paint;
       
   108             MTLSurfaceData dstData = (MTLSurfaceData)sg2d.surfaceData;
       
   109             BufferedImage bi = paint.getImage();
       
   110 
       
   111             // see if texture-non-pow2 extension is available
       
   112             if (!dstData.isTexNonPow2Available()) {
       
   113                 int imgw = bi.getWidth();
       
   114                 int imgh = bi.getHeight();
       
   115 
       
   116                 // verify that the texture image dimensions are pow2
       
   117                 if ((imgw & (imgw - 1)) != 0 || (imgh & (imgh - 1)) != 0) {
       
   118                     return false;
       
   119                 }
       
   120             }
       
   121 
       
   122             SurfaceData srcData =
       
   123                     dstData.getSourceSurfaceData(bi,
       
   124                             SunGraphics2D.TRANSFORM_ISIDENT,
       
   125                             CompositeType.SrcOver, null);
       
   126             if (!(srcData instanceof MTLSurfaceData)) {
       
   127                 // REMIND: this is a hack that attempts to cache the system
       
   128                 //         memory image from the TexturePaint instance into an
       
   129                 //         OpenGL texture...
       
   130                 srcData =
       
   131                         dstData.getSourceSurfaceData(bi,
       
   132                                 SunGraphics2D.TRANSFORM_ISIDENT,
       
   133                                 CompositeType.SrcOver, null);
       
   134                 if (!(srcData instanceof MTLSurfaceData)) {
       
   135                     return false;
       
   136                 }
       
   137             }
       
   138 
       
   139             // verify that the source surface is actually a texture
       
   140             MTLSurfaceData oglData = (MTLSurfaceData)srcData;
       
   141             if (oglData.getType() != MTLSurfaceData.TEXTURE) {
       
   142                 return false;
       
   143             }
       
   144 
       
   145             return true;
       
   146         }
       
   147     }
       
   148 
       
   149     /****************** Shared MultipleGradientPaint support ********************/
       
   150 
       
   151     private abstract static class MultiGradient extends MTLPaints {
       
   152         protected MultiGradient() {}
       
   153 
       
   154         /**
       
   155          * Returns true if the given MultipleGradientPaint instance can be
       
   156          * used by the accelerated MTLPaints.MultiGradient implementation.
       
   157          * A MultipleGradientPaint is considered valid if the following
       
   158          * conditions are met:
       
   159          *   - the number of gradient "stops" is <= MAX_FRACTIONS
       
   160          *   - the destination has support for fragment shaders
       
   161          */
       
   162         @Override
       
   163         boolean isPaintValid(SunGraphics2D sg2d) {
       
   164             MultipleGradientPaint paint = (MultipleGradientPaint)sg2d.paint;
       
   165             // REMIND: ugh, this creates garbage; would be nicer if
       
   166             // we had a MultipleGradientPaint.getNumStops() method...
       
   167             if (paint.getFractions().length > MULTI_MAX_FRACTIONS) {
       
   168                 return false;
       
   169             }
       
   170 
       
   171             MTLSurfaceData dstData = (MTLSurfaceData)sg2d.surfaceData;
       
   172             MTLGraphicsConfig gc = dstData.getMTLGraphicsConfig();
       
   173             if (!gc.isCapPresent(CAPS_EXT_GRAD_SHADER)) {
       
   174                 return false;
       
   175             }
       
   176 
       
   177             return true;
       
   178         }
       
   179     }
       
   180 
       
   181     /********************** LinearGradientPaint support *************************/
       
   182 
       
   183     private static class LinearGradient extends MultiGradient {
       
   184         private LinearGradient() {}
       
   185 
       
   186         @Override
       
   187         boolean isPaintValid(SunGraphics2D sg2d) {
       
   188             LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint;
       
   189 
       
   190             if (paint.getFractions().length == 2 &&
       
   191                     paint.getCycleMethod() != CycleMethod.REPEAT &&
       
   192                     paint.getColorSpace() != ColorSpaceType.LINEAR_RGB)
       
   193             {
       
   194                 // we can delegate to the optimized two-color gradient
       
   195                 // codepath, which does not require fragment shader support
       
   196                 return true;
       
   197             }
       
   198 
       
   199             return super.isPaintValid(sg2d);
       
   200         }
       
   201     }
       
   202 
       
   203     /********************** RadialGradientPaint support *************************/
       
   204 
       
   205     private static class RadialGradient extends MultiGradient {
       
   206         private RadialGradient() {}
       
   207     }
       
   208 }