653 lines · 24.4 KB · Java
RawDownload
/* * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.java2d.opengl; import java.awt.AlphaComposite;import java.awt.GraphicsEnvironment;import java.awt.Rectangle;import java.awt.Transparency;import java.awt.image.ColorModel;import java.awt.image.Raster;import sun.awt.SunHints;import sun.awt.image.PixelConverter;import sun.java2d.pipe.hw.AccelSurface;import sun.java2d.SunGraphics2D;import sun.java2d.SurfaceData;import sun.java2d.SurfaceDataProxy;import sun.java2d.loops.CompositeType;import sun.java2d.loops.GraphicsPrimitive;import sun.java2d.loops.MaskFill;import sun.java2d.loops.SurfaceType;import sun.java2d.pipe.ParallelogramPipe;import sun.java2d.pipe.PixelToParallelogramConverter;import sun.java2d.pipe.RenderBuffer;import sun.java2d.pipe.TextPipe;import static sun.java2d.pipe.BufferedOpCodes.*;import static sun.java2d.opengl.OGLContext.OGLContextCaps.*; /** * This class describes an OpenGL "surface", that is, a region of pixels * managed via OpenGL.  An OGLSurfaceData can be tagged with one of three * different SurfaceType objects for the purpose of registering loops, etc. * This diagram shows the hierarchy of OGL SurfaceTypes: * *                               Any *                             /     \ *                 OpenGLSurface     OpenGLTexture *                      | *               OpenGLSurfaceRTT * * OpenGLSurface * This kind of surface can be rendered to using OpenGL APIs.  It is also * possible to copy an OpenGLSurface to another OpenGLSurface (or to itself). * This is typically accomplished by calling MakeContextCurrent(dstSD, srcSD) * and then calling glCopyPixels() (although there are other techniques to * achieve the same goal). * * OpenGLTexture * This kind of surface cannot be rendered to using OpenGL (in the same sense * as in OpenGLSurface).  However, it is possible to upload a region of pixels * to an OpenGLTexture object via glTexSubImage2D().  One can also copy a * surface of type OpenGLTexture to an OpenGLSurface by binding the texture * to a quad and then rendering it to the destination surface (this process * is known as "texture mapping"). * * OpenGLSurfaceRTT * This kind of surface can be thought of as a sort of hybrid between * OpenGLSurface and OpenGLTexture, in that one can render to this kind of * surface as if it were of type OpenGLSurface, but the process of copying * this kind of surface to another is more like an OpenGLTexture.  (Note that * "RTT" stands for "render-to-texture".) * * In addition to these SurfaceType variants, we have also defined some * constants that describe in more detail the type of underlying OpenGL * surface.  This table helps explain the relationships between those * "type" constants and their corresponding SurfaceType: * * OGL Type          Corresponding SurfaceType * --------          ------------------------- * WINDOW            OpenGLSurface * PBUFFER           OpenGLSurface * TEXTURE           OpenGLTexture * FLIP_BACKBUFFER   OpenGLSurface * FBOBJECT          OpenGLSurfaceRTT */public abstract class OGLSurfaceData extends SurfaceData    implements AccelSurface {     /**     * OGL-specific surface types     *     * @see sun.java2d.pipe.hw.AccelSurface     */    public static final int PBUFFER         = RT_PLAIN;    public static final int FBOBJECT        = RT_TEXTURE;     /**     * Pixel formats     */    public static final int PF_INT_ARGB        = 0;    public static final int PF_INT_ARGB_PRE    = 1;    public static final int PF_INT_RGB         = 2;    public static final int PF_INT_RGBX        = 3;    public static final int PF_INT_BGR         = 4;    public static final int PF_INT_BGRX        = 5;    public static final int PF_USHORT_565_RGB  = 6;    public static final int PF_USHORT_555_RGB  = 7;    public static final int PF_USHORT_555_RGBX = 8;    public static final int PF_BYTE_GRAY       = 9;    public static final int PF_USHORT_GRAY     = 10;    public static final int PF_3BYTE_BGR       = 11;     /**     * SurfaceTypes     */    private static final String DESC_OPENGL_SURFACE = "OpenGL Surface";    private static final String DESC_OPENGL_SURFACE_RTT =        "OpenGL Surface (render-to-texture)";    private static final String DESC_OPENGL_TEXTURE = "OpenGL Texture";     static final SurfaceType OpenGLSurface =        SurfaceType.Any.deriveSubType(DESC_OPENGL_SURFACE,                                      PixelConverter.ArgbPre.instance);    static final SurfaceType OpenGLSurfaceRTT =        OpenGLSurface.deriveSubType(DESC_OPENGL_SURFACE_RTT);    static final SurfaceType OpenGLTexture =        SurfaceType.Any.deriveSubType(DESC_OPENGL_TEXTURE);     /** This will be true if the fbobject system property has been enabled. */    private static boolean isFBObjectEnabled;     /** This will be true if the lcdshader system property has been enabled.*/    private static boolean isLCDShaderEnabled;     /** This will be true if the biopshader system property has been enabled.*/    private static boolean isBIOpShaderEnabled;     /** This will be true if the gradshader system property has been enabled.*/    private static boolean isGradShaderEnabled;     private OGLGraphicsConfig graphicsConfig;    protected int type;    // these fields are set from the native code when the surface is    // initialized    private int nativeWidth, nativeHeight;     protected static OGLRenderer oglRenderPipe;    protected static PixelToParallelogramConverter oglTxRenderPipe;    protected static ParallelogramPipe oglAAPgramPipe;    protected static OGLTextRenderer oglTextPipe;    protected static OGLDrawImage oglImagePipe;     protected native boolean initTexture(long pData,                                         boolean isOpaque, boolean texNonPow2,                                         boolean texRect,                                         int width, int height);    protected native boolean initFBObject(long pData,                                          boolean isOpaque, boolean texNonPow2,                                          boolean texRect,                                          int width, int height);    protected native boolean initFlipBackbuffer(long pData);    protected abstract boolean initPbuffer(long pData, long pConfigInfo,                                           boolean isOpaque,                                           int width, int height);     private native int getTextureTarget(long pData);    private native int getTextureID(long pData);     static {        if (!GraphicsEnvironment.isHeadless()) {            // fbobject currently enabled by default; use "false" to disable            String fbo = (String)java.security.AccessController.doPrivileged(                new sun.security.action.GetPropertyAction(                    "sun.java2d.opengl.fbobject"));            isFBObjectEnabled = !"false".equals(fbo);             // lcdshader currently enabled by default; use "false" to disable            String lcd = (String)java.security.AccessController.doPrivileged(                new sun.security.action.GetPropertyAction(                    "sun.java2d.opengl.lcdshader"));            isLCDShaderEnabled = !"false".equals(lcd);             // biopshader currently enabled by default; use "false" to disable            String biop = (String)java.security.AccessController.doPrivileged(                new sun.security.action.GetPropertyAction(                    "sun.java2d.opengl.biopshader"));            isBIOpShaderEnabled = !"false".equals(biop);             // gradshader currently enabled by default; use "false" to disable            String grad = (String)java.security.AccessController.doPrivileged(                new sun.security.action.GetPropertyAction(                    "sun.java2d.opengl.gradshader"));            isGradShaderEnabled = !"false".equals(grad);             OGLRenderQueue rq = OGLRenderQueue.getInstance();            oglImagePipe = new OGLDrawImage();            oglTextPipe = new OGLTextRenderer(rq);            oglRenderPipe = new OGLRenderer(rq);            if (GraphicsPrimitive.tracingEnabled()) {                oglTextPipe = oglTextPipe.traceWrap();                //The wrapped oglRenderPipe will wrap the AA pipe as well...                //oglAAPgramPipe = oglRenderPipe.traceWrap();            }            oglAAPgramPipe = oglRenderPipe.getAAParallelogramPipe();            oglTxRenderPipe =                new PixelToParallelogramConverter(oglRenderPipe,                                                  oglRenderPipe,                                                  1.0, 0.25, true);             OGLBlitLoops.register();            OGLMaskFill.register();            OGLMaskBlit.register();        }    }     protected OGLSurfaceData(OGLGraphicsConfig gc,                             ColorModel cm, int type)    {        super(getCustomSurfaceType(type), cm);        this.graphicsConfig = gc;        this.type = type;        setBlitProxyKey(gc.getProxyKey());    }     @Override    public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {        return OGLSurfaceDataProxy.createProxy(srcData, graphicsConfig);    }     /**     * Returns the appropriate SurfaceType corresponding to the given OpenGL     * surface type constant (e.g. TEXTURE -> OpenGLTexture).     */    private static SurfaceType getCustomSurfaceType(int oglType) {        switch (oglType) {        case TEXTURE:            return OpenGLTexture;        case FBOBJECT:            return OpenGLSurfaceRTT;        case PBUFFER:        default:            return OpenGLSurface;        }    }     /**     * Note: This should only be called from the QFT under the AWT lock.     * This method is kept separate from the initSurface() method below just     * to keep the code a bit cleaner.     */    private void initSurfaceNow(int width, int height) {        boolean isOpaque = (getTransparency() == Transparency.OPAQUE);        boolean success = false;         switch (type) {        case PBUFFER:            success = initPbuffer(getNativeOps(),                                  graphicsConfig.getNativeConfigInfo(),                                  isOpaque,                                  width, height);            break;         case TEXTURE:            success = initTexture(getNativeOps(),                                  isOpaque, isTexNonPow2Available(),                                  isTexRectAvailable(),                                  width, height);            break;         case FBOBJECT:            success = initFBObject(getNativeOps(),                                   isOpaque, isTexNonPow2Available(),                                   isTexRectAvailable(),                                   width, height);            break;         case FLIP_BACKBUFFER:            success = initFlipBackbuffer(getNativeOps());            break;         default:            break;        }         if (!success) {            throw new OutOfMemoryError("can't create offscreen surface");        }    }     /**     * Initializes the appropriate OpenGL offscreen surface based on the value     * of the type parameter.  If the surface creation fails for any reason,     * an OutOfMemoryError will be thrown.     */    protected void initSurface(final int width, final int height) {        OGLRenderQueue rq = OGLRenderQueue.getInstance();        rq.lock();        try {            switch (type) {            case TEXTURE:            case PBUFFER:            case FBOBJECT:                // need to make sure the context is current before                // creating the texture (or pbuffer, or fbobject)                OGLContext.setScratchSurface(graphicsConfig);                break;            default:                break;            }            rq.flushAndInvokeNow(new Runnable() {                public void run() {                    initSurfaceNow(width, height);                }            });        } finally {            rq.unlock();        }    }     /**     * Returns the OGLContext for the GraphicsConfig associated with this     * surface.     */    public final OGLContext getContext() {        return graphicsConfig.getContext();    }     /**     * Returns the OGLGraphicsConfig associated with this surface.     */    final OGLGraphicsConfig getOGLGraphicsConfig() {        return graphicsConfig;    }     /**     * Returns one of the surface type constants defined above.     */    public final int getType() {        return type;    }     /**     * If this surface is backed by a texture object, returns the target     * for that texture (either GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB).     * Otherwise, this method will return zero.     */    public final int getTextureTarget() {        return getTextureTarget(getNativeOps());    }     /**     * If this surface is backed by a texture object, returns the texture ID     * for that texture.     * Otherwise, this method will return zero.     */    public final int getTextureID() {        return getTextureID(getNativeOps());    }     /**     * Returns native resource of specified {@code resType} associated with     * this surface.     *     * Specifically, for {@code OGLSurfaceData} this method returns the     * the following:     * <pre>     * TEXTURE              - texture id     * </pre>     *     * Note: the resource returned by this method is only valid on the rendering     * thread.     *     * @return native resource of specified type or 0L if     * such resource doesn't exist or can not be retrieved.     * @see sun.java2d.pipe.hw.AccelSurface#getNativeResource     */    public long getNativeResource(int resType) {        if (resType == TEXTURE) {            return getTextureID();        }        return 0L;    }     public Raster getRaster(int x, int y, int w, int h) {        throw new InternalError("not implemented yet");    }     /**     * For now, we can only render LCD text if:     *   - the fragment shader extension is available, and     *   - blending is disabled, and     *   - the source color is opaque     *   - and the destination is opaque     *     * Eventually, we could enhance the native OGL text rendering code     * and remove the above restrictions, but that would require significantly     * more code just to support a few uncommon cases.     */    public boolean canRenderLCDText(SunGraphics2D sg2d) {        return            graphicsConfig.isCapPresent(CAPS_EXT_LCD_SHADER) &&            sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&            sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR &&            sg2d.surfaceData.getTransparency() == Transparency.OPAQUE;    }     public void validatePipe(SunGraphics2D sg2d) {        TextPipe textpipe;        boolean validated = false;         // OGLTextRenderer handles both AA and non-AA text, but        // only works with the following modes:        // (Note: For LCD text we only enter this code path if        // canRenderLCDText() has already validated that the mode is        // CompositeType.SrcNoEa (opaque color), which will be subsumed        // by the CompositeType.SrcNoEa (any color) test below.)         if (/* CompositeType.SrcNoEa (any color) */            (sg2d.compositeState <= sg2d.COMP_ISCOPY &&             sg2d.paintState <= sg2d.PAINT_ALPHACOLOR)        ||             /* CompositeType.SrcOver (any color) */            (sg2d.compositeState == sg2d.COMP_ALPHA    &&             sg2d.paintState <= sg2d.PAINT_ALPHACOLOR &&             (((AlphaComposite)sg2d.composite).getRule() ==              AlphaComposite.SRC_OVER))                       ||             /* CompositeType.Xor (any color) */            (sg2d.compositeState == sg2d.COMP_XOR &&             sg2d.paintState <= sg2d.PAINT_ALPHACOLOR))        {            textpipe = oglTextPipe;        } else {            // do this to initialize textpipe correctly; we will attempt            // to override the non-text pipes below            super.validatePipe(sg2d);            textpipe = sg2d.textpipe;            validated = true;        }         PixelToParallelogramConverter txPipe = null;        OGLRenderer nonTxPipe = null;         if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {            if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) {                if (sg2d.compositeState <= sg2d.COMP_XOR) {                    txPipe = oglTxRenderPipe;                    nonTxPipe = oglRenderPipe;                }            } else if (sg2d.compositeState <= sg2d.COMP_ALPHA) {                if (OGLPaints.isValid(sg2d)) {                    txPipe = oglTxRenderPipe;                    nonTxPipe = oglRenderPipe;                }                // custom paints handled by super.validatePipe() below            }        } else {            if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) {                if (graphicsConfig.isCapPresent(CAPS_PS30) &&                    (sg2d.imageComp == CompositeType.SrcOverNoEa ||                     sg2d.imageComp == CompositeType.SrcOver))                {                    if (!validated) {                        super.validatePipe(sg2d);                        validated = true;                    }                    PixelToParallelogramConverter aaConverter =                        new PixelToParallelogramConverter(sg2d.shapepipe,                                                          oglAAPgramPipe,                                                          1.0/8.0, 0.499,                                                          false);                    sg2d.drawpipe = aaConverter;                    sg2d.fillpipe = aaConverter;                    sg2d.shapepipe = aaConverter;                } else if (sg2d.compositeState == sg2d.COMP_XOR) {                    // install the solid pipes when AA and XOR are both enabled                    txPipe = oglTxRenderPipe;                    nonTxPipe = oglRenderPipe;                }            }            // other cases handled by super.validatePipe() below        }         if (txPipe != null) {            if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) {                sg2d.drawpipe = txPipe;                sg2d.fillpipe = txPipe;            } else if (sg2d.strokeState != sg2d.STROKE_THIN) {

Lines 1–500 of 653.