001: /*
002: * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.java2d.opengl;
027:
028: import java.awt.GradientPaint;
029: import java.awt.LinearGradientPaint;
030: import java.awt.MultipleGradientPaint;
031: import java.awt.MultipleGradientPaint.ColorSpaceType;
032: import java.awt.MultipleGradientPaint.CycleMethod;
033: import java.awt.RadialGradientPaint;
034: import java.awt.TexturePaint;
035: import java.awt.image.BufferedImage;
036: import java.util.HashMap;
037: import java.util.Map;
038: import sun.java2d.SunGraphics2D;
039: import sun.java2d.SurfaceData;
040: import sun.java2d.loops.CompositeType;
041: import static sun.java2d.pipe.BufferedPaints.*;
042:
043: abstract class OGLPaints {
044:
045: /**
046: * Holds all registered implementations, using the corresponding
047: * SunGraphics2D.PAINT_* constant as the hash key.
048: */
049: private static Map<Integer, OGLPaints> impls = new HashMap<Integer, OGLPaints>(
050: 4, 1.0f);
051:
052: static {
053: impls.put(SunGraphics2D.PAINT_GRADIENT, new Gradient());
054: impls.put(SunGraphics2D.PAINT_LIN_GRADIENT,
055: new LinearGradient());
056: impls.put(SunGraphics2D.PAINT_RAD_GRADIENT,
057: new RadialGradient());
058: impls.put(SunGraphics2D.PAINT_TEXTURE, new Texture());
059: }
060:
061: /**
062: * Attempts to locate an implementation corresponding to the paint state
063: * of the provided SunGraphics2D object. If no implementation can be
064: * found, or if the paint cannot be accelerated under the conditions
065: * of the SunGraphics2D, this method returns false; otherwise, returns
066: * true.
067: */
068: static boolean isValid(SunGraphics2D sg2d) {
069: OGLPaints impl = impls.get(sg2d.paintState);
070: return (impl != null && impl.isPaintValid(sg2d));
071: }
072:
073: /**
074: * Returns true if this implementation is able to accelerate the
075: * Paint object associated with, and under the conditions of, the
076: * provided SunGraphics2D instance; otherwise returns false.
077: */
078: abstract boolean isPaintValid(SunGraphics2D sg2d);
079:
080: /************************* GradientPaint support ****************************/
081:
082: private static class Gradient extends OGLPaints {
083: private Gradient() {
084: }
085:
086: /**
087: * There are no restrictions for accelerating GradientPaint, so
088: * this method always returns true.
089: */
090: @Override
091: boolean isPaintValid(SunGraphics2D sg2d) {
092: return true;
093: }
094: }
095:
096: /************************** TexturePaint support ****************************/
097:
098: private static class Texture extends OGLPaints {
099: private Texture() {
100: }
101:
102: /**
103: * Returns true if the given TexturePaint instance can be used by the
104: * accelerated OGLPaints.Texture implementation. A TexturePaint is
105: * considered valid if the following conditions are met:
106: * - the texture image dimensions are power-of-two (or the
107: * GL_ARB_texture_non_power_of_two extension is present)
108: * - the texture image can be (or is already) cached in an OpenGL
109: * texture object
110: */
111: @Override
112: boolean isPaintValid(SunGraphics2D sg2d) {
113: TexturePaint paint = (TexturePaint) sg2d.paint;
114: OGLSurfaceData dstData = (OGLSurfaceData) sg2d.surfaceData;
115: BufferedImage bi = paint.getImage();
116:
117: // see if texture-non-pow2 extension is available
118: if (!dstData.isTexNonPow2Available()) {
119: int imgw = bi.getWidth();
120: int imgh = bi.getHeight();
121:
122: // verify that the texture image dimensions are pow2
123: if ((imgw & (imgw - 1)) != 0
124: || (imgh & (imgh - 1)) != 0) {
125: return false;
126: }
127: }
128:
129: SurfaceData srcData = dstData
130: .getSourceSurfaceData(bi, sg2d.TRANSFORM_ISIDENT,
131: CompositeType.SrcOver, null);
132: if (!(srcData instanceof OGLSurfaceData)) {
133: // REMIND: this is a hack that attempts to cache the system
134: // memory image from the TexturePaint instance into an
135: // OpenGL texture...
136: srcData = dstData.getSourceSurfaceData(bi,
137: sg2d.TRANSFORM_ISIDENT, CompositeType.SrcOver,
138: null);
139: if (!(srcData instanceof OGLSurfaceData)) {
140: return false;
141: }
142: }
143:
144: // verify that the source surface is actually a texture
145: OGLSurfaceData oglData = (OGLSurfaceData) srcData;
146: if (oglData.getType() != OGLSurfaceData.TEXTURE) {
147: return false;
148: }
149:
150: return true;
151: }
152: }
153:
154: /****************** Shared MultipleGradientPaint support ********************/
155:
156: private static abstract class MultiGradient extends OGLPaints {
157: protected MultiGradient() {
158: }
159:
160: /**
161: * Returns true if the given MultipleGradientPaint instance can be
162: * used by the accelerated OGLPaints.MultiGradient implementation.
163: * A MultipleGradientPaint is considered valid if the following
164: * conditions are met:
165: * - the number of gradient "stops" is <= MAX_FRACTIONS
166: * - the destination has support for fragment shaders
167: */
168: @Override
169: boolean isPaintValid(SunGraphics2D sg2d) {
170: MultipleGradientPaint paint = (MultipleGradientPaint) sg2d.paint;
171: // REMIND: ugh, this creates garbage; would be nicer if
172: // we had a MultipleGradientPaint.getNumStops() method...
173: if (paint.getFractions().length > MULTI_MAX_FRACTIONS) {
174: return false;
175: }
176:
177: OGLSurfaceData dstData = (OGLSurfaceData) sg2d.surfaceData;
178: OGLGraphicsConfig gc = dstData.getOGLGraphicsConfig();
179: if (!gc.isCapPresent(OGLContext.CAPS_EXT_GRAD_SHADER)) {
180: return false;
181: }
182:
183: return true;
184: }
185: }
186:
187: /********************** LinearGradientPaint support *************************/
188:
189: private static class LinearGradient extends MultiGradient {
190: private LinearGradient() {
191: }
192:
193: @Override
194: boolean isPaintValid(SunGraphics2D sg2d) {
195: LinearGradientPaint paint = (LinearGradientPaint) sg2d.paint;
196:
197: if (paint.getFractions().length == 2
198: && paint.getCycleMethod() != CycleMethod.REPEAT
199: && paint.getColorSpace() != ColorSpaceType.LINEAR_RGB) {
200: // we can delegate to the optimized two-color gradient
201: // codepath, which does not require fragment shader support
202: return true;
203: }
204:
205: return super .isPaintValid(sg2d);
206: }
207: }
208:
209: /********************** RadialGradientPaint support *************************/
210:
211: private static class RadialGradient extends MultiGradient {
212: private RadialGradient() {
213: }
214: }
215: }
|