alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (OGLSurfaceData.java)

This example Java source code file (OGLSurfaceData.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

awt, fbobject, image, java2d, ogldrawimage, oglrenderer, oglrenderqueue, opengl, openglsurface, openglsurfacertt, override, pbuffer, pixeltoparallelogramconverter, renderbuffer, string, surfacetype, texture

The OGLSurfaceData.java Java example source code

/*
 * Copyright (c) 2003, 2012, 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 <= SunGraphics2D.COMP_ISCOPY &&
             sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR)         ||

            /* CompositeType.SrcOver (any color) */
            (sg2d.compositeState == SunGraphics2D.COMP_ALPHA   &&
             sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
             (((AlphaComposite)sg2d.composite).getRule() ==
              AlphaComposite.SRC_OVER))                                 ||

            /* CompositeType.Xor (any color) */
            (sg2d.compositeState == SunGraphics2D.COMP_XOR &&
             sg2d.paintState <= SunGraphics2D.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 <= SunGraphics2D.PAINT_ALPHACOLOR) {
                if (sg2d.compositeState <= SunGraphics2D.COMP_XOR) {
                    txPipe = oglTxRenderPipe;
                    nonTxPipe = oglRenderPipe;
                }
            } else if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) {
                if (OGLPaints.isValid(sg2d)) {
                    txPipe = oglTxRenderPipe;
                    nonTxPipe = oglRenderPipe;
                }
                // custom paints handled by super.validatePipe() below
            }
        } else {
            if (sg2d.paintState <= SunGraphics2D.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 == SunGraphics2D.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 >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
                sg2d.drawpipe = txPipe;
                sg2d.fillpipe = txPipe;
            } else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {
                sg2d.drawpipe = txPipe;
                sg2d.fillpipe = nonTxPipe;
            } else {
                sg2d.drawpipe = nonTxPipe;
                sg2d.fillpipe = nonTxPipe;
            }
            // Note that we use the transforming pipe here because it
            // will examine the shape and possibly perform an optimized
            // operation if it can be simplified.  The simplifications
            // will be valid for all STROKE and TRANSFORM types.
            sg2d.shapepipe = txPipe;
        } else {
            if (!validated) {
                super.validatePipe(sg2d);
            }
        }

        // install the text pipe based on our earlier decision
        sg2d.textpipe = textpipe;

        // always override the image pipe with the specialized OGL pipe
        sg2d.imagepipe = oglImagePipe;
    }

    @Override
    protected MaskFill getMaskFill(SunGraphics2D sg2d) {
        if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR) {
            /*
             * We can only accelerate non-Color MaskFill operations if
             * all of the following conditions hold true:
             *   - there is an implementation for the given paintState
             *   - the current Paint can be accelerated for this destination
             *   - multitexturing is available (since we need to modulate
             *     the alpha mask texture with the paint texture)
             *
             * In all other cases, we return null, in which case the
             * validation code will choose a more general software-based loop.
             */
            if (!OGLPaints.isValid(sg2d) ||
                !graphicsConfig.isCapPresent(CAPS_MULTITEXTURE))
            {
                return null;
            }
        }
        return super.getMaskFill(sg2d);
    }

    public boolean copyArea(SunGraphics2D sg2d,
                            int x, int y, int w, int h, int dx, int dy)
    {
        if (sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE &&
            sg2d.compositeState < SunGraphics2D.COMP_XOR)
        {
            x += sg2d.transX;
            y += sg2d.transY;

            oglRenderPipe.copyArea(sg2d, x, y, w, h, dx, dy);

            return true;
        }
        return false;
    }

    public void flush() {
        invalidate();
        OGLRenderQueue rq = OGLRenderQueue.getInstance();
        rq.lock();
        try {
            // make sure we have a current context before
            // disposing the native resources (e.g. texture object)
            OGLContext.setScratchSurface(graphicsConfig);

            RenderBuffer buf = rq.getBuffer();
            rq.ensureCapacityAndAlignment(12, 4);
            buf.putInt(FLUSH_SURFACE);
            buf.putLong(getNativeOps());

            // this call is expected to complete synchronously, so flush now
            rq.flushNow();
        } finally {
            rq.unlock();
        }
    }

    /**
     * Disposes the native resources associated with the given OGLSurfaceData
     * (referenced by the pData parameter).  This method is invoked from
     * the native Dispose() method from the Disposer thread when the
     * Java-level OGLSurfaceData object is about to go away.  Note that we
     * also pass a reference to the native GLX/WGLGraphicsConfigInfo
     * (pConfigInfo) for the purposes of making a context current.
     */
    static void dispose(long pData, long pConfigInfo) {
        OGLRenderQueue rq = OGLRenderQueue.getInstance();
        rq.lock();
        try {
            // make sure we have a current context before
            // disposing the native resources (e.g. texture object)
            OGLContext.setScratchSurface(pConfigInfo);

            RenderBuffer buf = rq.getBuffer();
            rq.ensureCapacityAndAlignment(12, 4);
            buf.putInt(DISPOSE_SURFACE);
            buf.putLong(pData);

            // this call is expected to complete synchronously, so flush now
            rq.flushNow();
        } finally {
            rq.unlock();
        }
    }

    static void swapBuffers(long window) {
        OGLRenderQueue rq = OGLRenderQueue.getInstance();
        rq.lock();
        try {
            RenderBuffer buf = rq.getBuffer();
            rq.ensureCapacityAndAlignment(12, 4);
            buf.putInt(SWAP_BUFFERS);
            buf.putLong(window);
            rq.flushNow();
        } finally {
            rq.unlock();
        }
    }

    /**
     * Returns true if OpenGL textures can have non-power-of-two dimensions
     * when using the basic GL_TEXTURE_2D target.
     */
    boolean isTexNonPow2Available() {
        return graphicsConfig.isCapPresent(CAPS_TEXNONPOW2);
    }

    /**
     * Returns true if OpenGL textures can have non-power-of-two dimensions
     * when using the GL_TEXTURE_RECTANGLE_ARB target (only available when the
     * GL_ARB_texture_rectangle extension is present).
     */
    boolean isTexRectAvailable() {
        return graphicsConfig.isCapPresent(CAPS_EXT_TEXRECT);
    }

    public Rectangle getNativeBounds() {
        OGLRenderQueue rq = OGLRenderQueue.getInstance();
        rq.lock();
        try {
            return new Rectangle(nativeWidth, nativeHeight);
        } finally {
            rq.unlock();
        }
    }

    /**
     * Returns true if the surface is an on-screen window surface or
     * a FBO texture attached to an on-screen CALayer.
     *
     * Needed by Mac OS X port.
     */
    boolean isOnScreen() {
        return getType() == WINDOW;
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java OGLSurfaceData.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.