/*
 * Copyright 2003-2007 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.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.Transparency;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import sun.awt.SunHints;
import sun.awt.image.PixelConverter;
import sun.java2d.SunGraphics2D;
import sun.java2d.SurfaceData;
import sun.java2d.SurfaceDataProxy;
import sun.java2d.loops.GraphicsPrimitive;
import sun.java2d.loops.MaskFill;
import sun.java2d.loops.SurfaceType;
import sun.java2d.pipe.PixelToShapeConverter;
import sun.java2d.pipe.RenderBuffer;
import sun.java2d.pipe.RenderQueue;
import sun.java2d.pipe.TextPipe;
import static sun.java2d.pipe.BufferedOpCodes.*;
import static sun.java2d.opengl.OGLContext.*;

/**
 * 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 {

    /**
     * OGL-specific surface types
     */
    public static final int UNDEFINED       = 0;
    public static final int WINDOW          = 1;
    public static final int PBUFFER         = 2;
    public static final int TEXTURE         = 3;
    public static final int FLIP_BACKBUFFER = 4;
    public static final int FBOBJECT        = 5;

    /**
     * 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;

    /**
     * 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;
    private int textureTarget;
    protected int type;

    protected static OGLRenderer oglRenderPipe;
    protected static PixelToShapeConverter oglTxRenderPipe;
    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);

    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();
                oglRenderPipe = oglRenderPipe.traceWrap();
            }
            oglTxRenderPipe = new PixelToShapeConverter(oglRenderPipe);

            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) {
            textureTarget = getTextureTarget(getNativeOps());
        } else {
            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.
     */
    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.
     */
    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.
     */
    final int getTextureTarget() {
        return textureTarget;
    }

    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
     *
     * 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(OGLContext.CAPS_EXT_LCD_SHADER) &&
            sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
            sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR;
    }

    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;
        }

        PixelToShapeConverter 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 &&
                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) {
                sg2d.drawpipe = txPipe;
                sg2d.fillpipe = nonTxPipe;
            } else {
                sg2d.drawpipe = nonTxPipe;
                sg2d.fillpipe = nonTxPipe;
            }
            sg2d.shapepipe = nonTxPipe;
        } 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 > sg2d.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_EXT_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 < sg2d.TRANSFORM_TRANSLATESCALE &&
            sg2d.compositeState < sg2d.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(OGLContext.CAPS_EXT_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(OGLContext.CAPS_EXT_TEXRECT);
    }
}
