0N/A/*
2362N/A * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.java2d.opengl;
0N/A
0N/Aimport java.awt.GradientPaint;
0N/Aimport java.awt.LinearGradientPaint;
0N/Aimport java.awt.MultipleGradientPaint;
0N/Aimport java.awt.MultipleGradientPaint.ColorSpaceType;
0N/Aimport java.awt.MultipleGradientPaint.CycleMethod;
0N/Aimport java.awt.RadialGradientPaint;
0N/Aimport java.awt.TexturePaint;
0N/Aimport java.awt.image.BufferedImage;
0N/Aimport java.util.HashMap;
0N/Aimport java.util.Map;
0N/Aimport sun.java2d.SunGraphics2D;
0N/Aimport sun.java2d.SurfaceData;
0N/Aimport sun.java2d.loops.CompositeType;
0N/Aimport static sun.java2d.pipe.BufferedPaints.*;
430N/Aimport static sun.java2d.opengl.OGLContext.OGLContextCaps.*;
0N/A
0N/Aabstract class OGLPaints {
0N/A
0N/A /**
0N/A * Holds all registered implementations, using the corresponding
0N/A * SunGraphics2D.PAINT_* constant as the hash key.
0N/A */
0N/A private static Map<Integer, OGLPaints> impls =
0N/A new HashMap<Integer, OGLPaints>(4, 1.0f);
0N/A
0N/A static {
0N/A impls.put(SunGraphics2D.PAINT_GRADIENT, new Gradient());
0N/A impls.put(SunGraphics2D.PAINT_LIN_GRADIENT, new LinearGradient());
0N/A impls.put(SunGraphics2D.PAINT_RAD_GRADIENT, new RadialGradient());
0N/A impls.put(SunGraphics2D.PAINT_TEXTURE, new Texture());
0N/A }
0N/A
0N/A /**
0N/A * Attempts to locate an implementation corresponding to the paint state
0N/A * of the provided SunGraphics2D object. If no implementation can be
0N/A * found, or if the paint cannot be accelerated under the conditions
0N/A * of the SunGraphics2D, this method returns false; otherwise, returns
0N/A * true.
0N/A */
0N/A static boolean isValid(SunGraphics2D sg2d) {
0N/A OGLPaints impl = impls.get(sg2d.paintState);
0N/A return (impl != null && impl.isPaintValid(sg2d));
0N/A }
0N/A
0N/A /**
0N/A * Returns true if this implementation is able to accelerate the
0N/A * Paint object associated with, and under the conditions of, the
0N/A * provided SunGraphics2D instance; otherwise returns false.
0N/A */
0N/A abstract boolean isPaintValid(SunGraphics2D sg2d);
0N/A
0N/A/************************* GradientPaint support ****************************/
0N/A
0N/A private static class Gradient extends OGLPaints {
0N/A private Gradient() {}
0N/A
0N/A /**
0N/A * There are no restrictions for accelerating GradientPaint, so
0N/A * this method always returns true.
0N/A */
0N/A @Override
0N/A boolean isPaintValid(SunGraphics2D sg2d) {
0N/A return true;
0N/A }
0N/A }
0N/A
0N/A/************************** TexturePaint support ****************************/
0N/A
0N/A private static class Texture extends OGLPaints {
0N/A private Texture() {}
0N/A
0N/A /**
0N/A * Returns true if the given TexturePaint instance can be used by the
0N/A * accelerated OGLPaints.Texture implementation. A TexturePaint is
0N/A * considered valid if the following conditions are met:
0N/A * - the texture image dimensions are power-of-two (or the
0N/A * GL_ARB_texture_non_power_of_two extension is present)
0N/A * - the texture image can be (or is already) cached in an OpenGL
0N/A * texture object
0N/A */
0N/A @Override
0N/A boolean isPaintValid(SunGraphics2D sg2d) {
0N/A TexturePaint paint = (TexturePaint)sg2d.paint;
0N/A OGLSurfaceData dstData = (OGLSurfaceData)sg2d.surfaceData;
0N/A BufferedImage bi = paint.getImage();
0N/A
0N/A // see if texture-non-pow2 extension is available
0N/A if (!dstData.isTexNonPow2Available()) {
0N/A int imgw = bi.getWidth();
0N/A int imgh = bi.getHeight();
0N/A
0N/A // verify that the texture image dimensions are pow2
0N/A if ((imgw & (imgw - 1)) != 0 || (imgh & (imgh - 1)) != 0) {
0N/A return false;
0N/A }
0N/A }
0N/A
0N/A SurfaceData srcData =
0N/A dstData.getSourceSurfaceData(bi, sg2d.TRANSFORM_ISIDENT,
0N/A CompositeType.SrcOver, null);
0N/A if (!(srcData instanceof OGLSurfaceData)) {
0N/A // REMIND: this is a hack that attempts to cache the system
0N/A // memory image from the TexturePaint instance into an
0N/A // OpenGL texture...
0N/A srcData =
0N/A dstData.getSourceSurfaceData(bi, sg2d.TRANSFORM_ISIDENT,
0N/A CompositeType.SrcOver, null);
0N/A if (!(srcData instanceof OGLSurfaceData)) {
0N/A return false;
0N/A }
0N/A }
0N/A
0N/A // verify that the source surface is actually a texture
0N/A OGLSurfaceData oglData = (OGLSurfaceData)srcData;
0N/A if (oglData.getType() != OGLSurfaceData.TEXTURE) {
0N/A return false;
0N/A }
0N/A
0N/A return true;
0N/A }
0N/A }
0N/A
0N/A/****************** Shared MultipleGradientPaint support ********************/
0N/A
0N/A private static abstract class MultiGradient extends OGLPaints {
0N/A protected MultiGradient() {}
0N/A
0N/A /**
0N/A * Returns true if the given MultipleGradientPaint instance can be
0N/A * used by the accelerated OGLPaints.MultiGradient implementation.
0N/A * A MultipleGradientPaint is considered valid if the following
0N/A * conditions are met:
0N/A * - the number of gradient "stops" is <= MAX_FRACTIONS
0N/A * - the destination has support for fragment shaders
0N/A */
0N/A @Override
0N/A boolean isPaintValid(SunGraphics2D sg2d) {
0N/A MultipleGradientPaint paint = (MultipleGradientPaint)sg2d.paint;
0N/A // REMIND: ugh, this creates garbage; would be nicer if
0N/A // we had a MultipleGradientPaint.getNumStops() method...
0N/A if (paint.getFractions().length > MULTI_MAX_FRACTIONS) {
0N/A return false;
0N/A }
0N/A
0N/A OGLSurfaceData dstData = (OGLSurfaceData)sg2d.surfaceData;
0N/A OGLGraphicsConfig gc = dstData.getOGLGraphicsConfig();
430N/A if (!gc.isCapPresent(CAPS_EXT_GRAD_SHADER)) {
0N/A return false;
0N/A }
0N/A
0N/A return true;
0N/A }
0N/A }
0N/A
0N/A/********************** LinearGradientPaint support *************************/
0N/A
0N/A private static class LinearGradient extends MultiGradient {
0N/A private LinearGradient() {}
0N/A
0N/A @Override
0N/A boolean isPaintValid(SunGraphics2D sg2d) {
0N/A LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint;
0N/A
0N/A if (paint.getFractions().length == 2 &&
0N/A paint.getCycleMethod() != CycleMethod.REPEAT &&
0N/A paint.getColorSpace() != ColorSpaceType.LINEAR_RGB)
0N/A {
0N/A // we can delegate to the optimized two-color gradient
0N/A // codepath, which does not require fragment shader support
0N/A return true;
0N/A }
0N/A
0N/A return super.isPaintValid(sg2d);
0N/A }
0N/A }
0N/A
0N/A/********************** RadialGradientPaint support *************************/
0N/A
0N/A private static class RadialGradient extends MultiGradient {
0N/A private RadialGradient() {}
0N/A }
0N/A}