/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.renderscript;

import android.compat.annotation.UnsupportedAppUsage;


/**
 * @hide
 * <p>ProgramStore contains a set of parameters that control how
 * the graphics hardware handles writes to the framebuffer.
 * It could be used to:</p>
 * <ul>
 *   <li>enable/disable depth testing</li>
 *   <li>specify wheather depth writes are performed</li>
 *   <li>setup various blending modes for use in effects like
 *     transparency</li>
 *   <li>define write masks for color components written into the
 *     framebuffer</li>
 *  </ul>
 *
 **/
public class ProgramStore extends BaseObj {
    /**
    * Specifies the function used to determine whether a fragment
    * will be drawn during the depth testing stage in the rendering
    * pipeline by comparing its value with that already in the depth
    * buffer. DepthFunc is only valid when depth buffer is present
    * and depth testing is enabled
    */
    public enum DepthFunc {

        /**
        * Always drawn
        */
        @UnsupportedAppUsage
        ALWAYS (0),
        /**
        * Drawn if the incoming depth value is less than that in the
        * depth buffer
        */
        @UnsupportedAppUsage
        LESS (1),
        /**
        * Drawn if the incoming depth value is less or equal to that in
        * the depth buffer
        */
        LESS_OR_EQUAL (2),
        /**
        * Drawn if the incoming depth value is greater than that in the
        * depth buffer
        */
        GREATER (3),
        /**
        * Drawn if the incoming depth value is greater or equal to that
        * in the depth buffer
        */
        GREATER_OR_EQUAL (4),
        /**
        * Drawn if the incoming depth value is equal to that in the
        * depth buffer
        */
        EQUAL (5),
        /**
        * Drawn if the incoming depth value is not equal to that in the
        * depth buffer
        */
        NOT_EQUAL (6);

        int mID;
        DepthFunc(int id) {
            mID = id;
        }
    }

    /**
    * Specifies the functions used to combine incoming pixels with
    * those already in the frame buffer.
    *
    * BlendSrcFunc describes how the coefficient used to scale the
    * source pixels during the blending operation is computed
    *
    */
    public enum BlendSrcFunc {
        ZERO (0),
        @UnsupportedAppUsage
        ONE (1),
        DST_COLOR (2),
        ONE_MINUS_DST_COLOR (3),
        @UnsupportedAppUsage
        SRC_ALPHA (4),
        ONE_MINUS_SRC_ALPHA (5),
        DST_ALPHA (6),
        ONE_MINUS_DST_ALPHA (7),
        SRC_ALPHA_SATURATE (8);

        int mID;
        BlendSrcFunc(int id) {
            mID = id;
        }
    }

    /**
    * Specifies the functions used to combine incoming pixels with
    * those already in the frame buffer.
    *
    * BlendDstFunc describes how the coefficient used to scale the
    * pixels already in the framebuffer is computed during the
    * blending operation
    *
    */
    public enum BlendDstFunc {
        @UnsupportedAppUsage
        ZERO (0),
        @UnsupportedAppUsage
        ONE (1),
        SRC_COLOR (2),
        ONE_MINUS_SRC_COLOR (3),
        SRC_ALPHA (4),
        @UnsupportedAppUsage
        ONE_MINUS_SRC_ALPHA (5),
        DST_ALPHA (6),
        ONE_MINUS_DST_ALPHA (7);

        int mID;
        BlendDstFunc(int id) {
            mID = id;
        }
    }

    DepthFunc mDepthFunc;
    boolean mDepthMask;
    boolean mColorMaskR;
    boolean mColorMaskG;
    boolean mColorMaskB;
    boolean mColorMaskA;
    BlendSrcFunc mBlendSrc;
    BlendDstFunc mBlendDst;
    boolean mDither;

    ProgramStore(long id, RenderScript rs) {
        super(id, rs);
    }

    /**
    * Returns the function used to test writing into the depth
    * buffer
    * @return depth function
    */
    public DepthFunc getDepthFunc() {
        return mDepthFunc;
    }

    /**
    * Queries whether writes are enabled into the depth buffer
    * @return depth mask
    */
    public boolean isDepthMaskEnabled() {
        return mDepthMask;
    }

    /**
    * Queries whether red channel is written
    * @return red color channel mask
    */
    public boolean isColorMaskRedEnabled() {
        return mColorMaskR;
    }

    /**
    * Queries whether green channel is written
    * @return green color channel mask
    */
    public boolean isColorMaskGreenEnabled() {
        return mColorMaskG;
    }

    /**
    * Queries whether blue channel is written
    * @return blue color channel mask
    */
    public boolean isColorMaskBlueEnabled() {
        return mColorMaskB;
    }

    /**
    * Queries whether alpha channel is written
    * @return alpha channel mask
    */
    public boolean isColorMaskAlphaEnabled() {
        return mColorMaskA;
    }

    /**
    * Specifies how the source blending factor is computed
    * @return source blend function
    */
    public BlendSrcFunc getBlendSrcFunc() {
        return mBlendSrc;
    }

    /**
    * Specifies how the destination blending factor is computed
    * @return destination blend function
    */
    public BlendDstFunc getBlendDstFunc() {
        return mBlendDst;
    }

    /**
    * Specifies whether colors are dithered before writing into the
    * framebuffer
    * @return whether dither is enabled
    */
    public boolean isDitherEnabled() {
        return mDither;
    }

    /**
    * Returns a pre-defined program store object with the following
    * characteristics:
    *  - incoming pixels are drawn if their depth value is less than
    *    the stored value in the depth buffer. If the pixel is
    *    drawn, its value is also stored in the depth buffer
    *  - incoming pixels override the value stored in the color
    *    buffer if it passes the depth test
    *
    *  @param rs Context to which the program will belong.
    **/
    public static ProgramStore BLEND_NONE_DEPTH_TEST(RenderScript rs) {
        if(rs.mProgramStore_BLEND_NONE_DEPTH_TEST == null) {
            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
            builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
            builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
            builder.setDitherEnabled(false);
            builder.setDepthMaskEnabled(true);
            rs.mProgramStore_BLEND_NONE_DEPTH_TEST = builder.create();
        }
        return rs.mProgramStore_BLEND_NONE_DEPTH_TEST;
    }
    /**
    * Returns a pre-defined program store object with the following
    * characteristics:
    *  - incoming pixels always pass the depth test and their value
    *    is not stored in the depth buffer
    *  - incoming pixels override the value stored in the color
    *    buffer
    *
    *  @param rs Context to which the program will belong.
    **/
    public static ProgramStore BLEND_NONE_DEPTH_NONE(RenderScript rs) {
        if(rs.mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH == null) {
            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
            builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
            builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
            builder.setDitherEnabled(false);
            builder.setDepthMaskEnabled(false);
            rs.mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH = builder.create();
        }
        return rs.mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH;
    }
    /**
    * Returns a pre-defined program store object with the following
    * characteristics:
    *  - incoming pixels are drawn if their depth value is less than
    *    the stored value in the depth buffer. If the pixel is
    *    drawn, its value is also stored in the depth buffer
    *  - if the incoming (Source) pixel passes depth test, its value
    *    is combined with the stored color (Dest) using the
    *    following formula
    *  Final.RGB = Source.RGB * Source.A + Dest.RGB * (1 - Source.A)
    *
    *  @param rs Context to which the program will belong.
    **/
    public static ProgramStore BLEND_ALPHA_DEPTH_TEST(RenderScript rs) {
        if(rs.mProgramStore_BLEND_ALPHA_DEPTH_TEST == null) {
            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
            builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
            builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
            builder.setDitherEnabled(false);
            builder.setDepthMaskEnabled(true);
            rs.mProgramStore_BLEND_ALPHA_DEPTH_TEST = builder.create();
        }
        return rs.mProgramStore_BLEND_ALPHA_DEPTH_TEST;
    }
    /**
    * Returns a pre-defined program store object with the following
    * characteristics:
    *  - incoming pixels always pass the depth test and their value
    *    is not stored in the depth buffer
    *  - incoming pixel's value is combined with the stored color
    *    (Dest) using the following formula
    *  Final.RGB = Source.RGB * Source.A + Dest.RGB * (1 - Source.A)
    *
    *  @param rs Context to which the program will belong.
    **/
    @UnsupportedAppUsage
    public static ProgramStore BLEND_ALPHA_DEPTH_NONE(RenderScript rs) {
        if(rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH == null) {
            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
            builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
            builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
            builder.setDitherEnabled(false);
            builder.setDepthMaskEnabled(false);
            rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH = builder.create();
        }
        return rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH;
    }

    /**
    * Builder class for ProgramStore object. If the builder is left
    * empty, the equivalent of BLEND_NONE_DEPTH_NONE would be
    * returned
    */
    public static class Builder {
        RenderScript mRS;
        DepthFunc mDepthFunc;
        boolean mDepthMask;
        boolean mColorMaskR;
        boolean mColorMaskG;
        boolean mColorMaskB;
        boolean mColorMaskA;
        BlendSrcFunc mBlendSrc;
        BlendDstFunc mBlendDst;
        boolean mDither;

        @UnsupportedAppUsage
        public Builder(RenderScript rs) {
            mRS = rs;
            mDepthFunc = DepthFunc.ALWAYS;
            mDepthMask = false;
            mColorMaskR = true;
            mColorMaskG = true;
            mColorMaskB = true;
            mColorMaskA = true;
            mBlendSrc = BlendSrcFunc.ONE;
            mBlendDst = BlendDstFunc.ZERO;
        }

        /**
        * Specifies the depth testing behavior
        *
        * @param func function used for depth testing
        *
        * @return this
        */
        @UnsupportedAppUsage
        public Builder setDepthFunc(DepthFunc func) {
            mDepthFunc = func;
            return this;
        }

        /**
        * Enables writes into the depth buffer
        *
        * @param enable specifies whether depth writes are
        *         enabled or disabled
        *
        * @return this
        */
        @UnsupportedAppUsage
        public Builder setDepthMaskEnabled(boolean enable) {
            mDepthMask = enable;
            return this;
        }

        /**
        * Enables writes into the color buffer
        *
        * @param r specifies whether red channel is written
        * @param g specifies whether green channel is written
        * @param b specifies whether blue channel is written
        * @param a specifies whether alpha channel is written
        *
        * @return this
        */
        public Builder setColorMaskEnabled(boolean r, boolean g, boolean b, boolean a) {
            mColorMaskR = r;
            mColorMaskG = g;
            mColorMaskB = b;
            mColorMaskA = a;
            return this;
        }

        /**
        * Specifies how incoming pixels are combined with the pixels
        * stored in the framebuffer
        *
        * @param src specifies how the source blending factor is
        *            computed
        * @param dst specifies how the destination blending factor is
        *            computed
        *
        * @return this
        */
        @UnsupportedAppUsage
        public Builder setBlendFunc(BlendSrcFunc src, BlendDstFunc dst) {
            mBlendSrc = src;
            mBlendDst = dst;
            return this;
        }

        /**
        * Enables dithering
        *
        * @param enable specifies whether dithering is enabled or
        *               disabled
        *
        * @return this
        */
        @UnsupportedAppUsage
        public Builder setDitherEnabled(boolean enable) {
            mDither = enable;
            return this;
        }

        /**
        * Creates a program store from the current state of the builder
        */
        @UnsupportedAppUsage
        public ProgramStore create() {
            mRS.validate();
            long id = mRS.nProgramStoreCreate(mColorMaskR, mColorMaskG, mColorMaskB, mColorMaskA,
                                             mDepthMask, mDither,
                                             mBlendSrc.mID, mBlendDst.mID, mDepthFunc.mID);
            ProgramStore programStore = new ProgramStore(id, mRS);
            programStore.mDepthFunc = mDepthFunc;
            programStore.mDepthMask = mDepthMask;
            programStore.mColorMaskR = mColorMaskR;
            programStore.mColorMaskG = mColorMaskG;
            programStore.mColorMaskB = mColorMaskB;
            programStore.mColorMaskA = mColorMaskA;
            programStore.mBlendSrc = mBlendSrc;
            programStore.mBlendDst = mBlendDst;
            programStore.mDither = mDither;
            return programStore;
        }
    }

}




