m3g/m3gcore11/src/m3g_compositingmode.c
author Faisal Memon <faisal.memon@nokia.com>
Thu, 09 Sep 2010 18:17:30 +0100
branchNewGraphicsArchitecture
changeset 175 c03ff11acab3
parent 0 5d03bc08d59c
permissions -rw-r--r--
Export new s4 egl extensions bitmap for the SF wiki

/*
* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: CompositingMode implementation
*
*/


/*!
 * \internal
 * \file
 * \brief CompositingMode implementation
 */

#ifndef M3G_CORE_INCLUDE
#   error included by m3g_core.c; do not compile separately.
#endif

#include "m3g_compositingmode.h"
#include "m3g_interface.h"

/*----------------------------------------------------------------------
 * Internal functions
 *--------------------------------------------------------------------*/

/*!
 * \internal
 * \brief Applies default CompositingMode to OpenGL.
 */
static void m3gApplyDefaultCompositingMode(M3Gbool alphaWrite)
{
    /* depth write = true */
    glDepthFunc(GL_LEQUAL);
    glDepthMask(GL_TRUE);

    /* colorWrite = true */
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, alphaWrite);

    /* threshold = 0.0 */
    glAlphaFunc(GL_GEQUAL, 0.0f);
    glDisable(GL_ALPHA_TEST);

    /* blend = REPLACE */
    glDisable(GL_BLEND);

    /* factor = 0 && units = 0 */
    glDisable(GL_POLYGON_OFFSET_FILL);
}

/*!
 * \internal
 * \brief Applies CompositingMode to OpenGL.
 *
 * \param compositingMode CompositingMode object
 */
static void m3gApplyCompositingMode(CompositingMode *compositingMode, RenderContext *ctx)
{
	M3Gbool alphaWrite = m3gGetAlphaWrite(ctx);

	if (compositingMode != NULL) {

        glDepthFunc(compositingMode->depthTest ? GL_LEQUAL : GL_ALWAYS);
        glDepthMask(compositingMode->depthWrite);

        if (m3gGetColorMaskWorkaround(M3G_INTERFACE(compositingMode))) {
            glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        }
        else {
            glColorMask(compositingMode->colorWrite,
                        compositingMode->colorWrite,
                        compositingMode->colorWrite,
						alphaWrite & compositingMode->alphaWrite);
        }

        if (compositingMode->alphaThreshold == 0.0f) {
            glDisable(GL_ALPHA_TEST);
        }
        else {
            glAlphaFunc(GL_GEQUAL, compositingMode->alphaThreshold);
            glEnable(GL_ALPHA_TEST);
        }

        if (compositingMode->blendingMode == M3G_REPLACE) {
            glDisable(GL_BLEND);
        }
        else {
            M3Gint src = GL_ONE;
            M3Gint dst = GL_ZERO;
            switch (compositingMode->blendingMode) {
                case M3G_ALPHA_ADD:
                    src = GL_SRC_ALPHA;
                    dst = GL_ONE;
                    break;
                case M3G_ALPHA_BLEND:
                    src = GL_SRC_ALPHA;
                    dst = GL_ONE_MINUS_SRC_ALPHA;
                    break;
                case M3G_MODULATE:
                    src = GL_ZERO;
                    dst = GL_SRC_COLOR;
                    break;
                case M3G_MODULATE_X2:
                    src = GL_DST_COLOR;
                    dst = GL_SRC_COLOR;
                    break;
            }
            glBlendFunc(src, dst);
            glEnable(GL_BLEND);
        }

        glPolygonOffset(compositingMode->factor, compositingMode->units);
        if (compositingMode->factor != 0 || compositingMode->units != 0) {
            glEnable(GL_POLYGON_OFFSET_FILL);
        }
        else {
            glDisable(GL_POLYGON_OFFSET_FILL);
        }
    }
    else {
		m3gApplyDefaultCompositingMode(alphaWrite);
    }
    M3G_ASSERT_GL;
}

/*!
 * \internal
 * \brief Duplicates a CompositingMode object.
 *
 * \param originalObj original CompositingMode object
 * \param cloneObj pointer to cloned CompositingMode object
 * \param pairs array for all object-duplicate pairs
 * \param numPairs number of pairs
 */
static M3Gbool m3gCompositingModeDuplicate(const Object *originalObj,
                                           Object **cloneObj,
                                           Object **pairs,
                                           M3Gint *numPairs)
{
    CompositingMode *original = (CompositingMode *)originalObj;
    CompositingMode *clone =
        (CompositingMode *)m3gCreateCompositingMode(originalObj->interface);
    *cloneObj = (Object *)clone;
    if (*cloneObj == NULL) {
        return M3G_FALSE;
    }

    if(m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
        clone->blendingMode = original->blendingMode;
        clone->alphaThreshold = original->alphaThreshold;
        clone->depthTest = original->depthTest;
        clone->depthWrite = original->depthWrite;
        clone->colorWrite = original->colorWrite;
        clone->alphaWrite = original->alphaWrite;
        clone->factor = original->factor;
        clone->units = original->units;
        return M3G_TRUE;
    }
    else {
        return M3G_FALSE;
    }
}

/*----------------------------------------------------------------------
 * Virtual function table
 *--------------------------------------------------------------------*/

static const ObjectVFTable m3gvf_CompositingMode = {
    m3gObjectApplyAnimation,
    m3gObjectIsCompatible,
    m3gObjectUpdateProperty,
    m3gObjectDoGetReferences,
    m3gObjectFindID,
    m3gCompositingModeDuplicate,
    m3gDestroyObject
};


/*----------------------------------------------------------------------
 * Public API functions
 *--------------------------------------------------------------------*/

/*!
 * \brief Creates a new CompositingMode object.
 *
 * \param interface     M3G interface
 * \retval CompositingMode new CompositingMode object
 * \retval NULL CompositingMode creating failed
 */
M3G_API M3GCompositingMode m3gCreateCompositingMode(M3GInterface interface)
{
    Interface *m3g = (Interface *) interface;
    M3G_VALIDATE_INTERFACE(m3g);

    {
        CompositingMode *compositingMode = m3gAllocZ(m3g, sizeof(CompositingMode));

        if (compositingMode != NULL) {
            m3gInitObject(&compositingMode->object, m3g,
                          M3G_CLASS_COMPOSITING_MODE);
    
            compositingMode->blendingMode = M3G_REPLACE;
            compositingMode->alphaThreshold = 0.0f;
            compositingMode->depthTest = GL_TRUE;
            compositingMode->depthTest = GL_TRUE;
            compositingMode->depthWrite = GL_TRUE;
            compositingMode->colorWrite = GL_TRUE;
            compositingMode->alphaWrite = GL_TRUE;
            compositingMode->factor = 0.0f;
            compositingMode->units = 0.0f;
        }

        return (M3GCompositingMode) compositingMode;
    }
}

/*!
 * \brief Set blending mode.
 *
 * \param handle CompositingMode object
 * \param mode blending mode
 */
M3G_API void m3gSetBlending(M3GCompositingMode handle, M3Gint mode)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    if (mode != M3G_REPLACE && mode != M3G_ALPHA_BLEND && mode != M3G_MODULATE && mode != M3G_MODULATE_X2 && mode != M3G_ALPHA_ADD) {
        m3gRaiseError(M3G_INTERFACE(compositingMode), M3G_INVALID_VALUE);
        return;
    }
    M3G_VALIDATE_OBJECT(compositingMode);
    compositingMode->blendingMode = mode;
}

/*!
 * \brief Get blending mode.
 *
 * \param handle CompositingMode object
 * \return blending mode
 */
M3G_API M3Gint m3gGetBlending(M3GCompositingMode handle)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    return compositingMode->blendingMode;
}

/*!
 * \brief Set alpha threshold [0, 1].
 *
 * \param handle CompositingMode object
 * \param threshold alpha threshold [0, 1]
 */
M3G_API void m3gSetAlphaThreshold(M3GCompositingMode handle,
                                  M3Gfloat threshold)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    if (!m3gInRangef(threshold, 0.0f, 1.0f)) {
        m3gRaiseError(M3G_INTERFACE(compositingMode), M3G_INVALID_VALUE);
        return;
    }
    compositingMode->alphaThreshold = threshold;
}

/*!
 * \brief Get alpha threshold.
 *
 * \param handle CompositingMode object
 * \return alpha threshold
 */
M3G_API M3Gfloat m3gGetAlphaThreshold(M3GCompositingMode handle)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    return compositingMode->alphaThreshold;
}

/*!
 * \brief Set depth test enable.
 *
 * \param handle CompositingMode object
 * \param enable depth test enable
 */
M3G_API void m3gEnableDepthTest(M3GCompositingMode handle, M3Gbool enable)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    compositingMode->depthTest = (GLboolean) enable;
}

/*!
 * \brief Set depth write enable.
 *
 * \param handle CompositingMode object
 * \param enable depth write enable
 */
M3G_API void m3gEnableDepthWrite(M3GCompositingMode handle, M3Gbool enable)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    compositingMode->depthWrite = (GLboolean) enable;
}

/*!
 * \brief Set color write enable.
 *
 * \param handle CompositingMode object
 * \param enable color write enable
 */
M3G_API void m3gEnableColorWrite(M3GCompositingMode handle, M3Gbool enable)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    compositingMode->colorWrite = (GLboolean) enable;
}

/*!
 * \brief Set depth offset with factor and units.
 *
 * \param handle CompositingMode object
 * \param factor slope dependent depth offset
 * \param units constant depth offset
 */
M3G_API void m3gSetDepthOffset(M3GCompositingMode handle,
                               M3Gfloat factor, M3Gfloat units)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    compositingMode->factor = factor;
    compositingMode->units = units;
}

/*!
 * \brief Get depth offset factor.
 *
 * \param handle CompositingMode object
 * \return slope dependent depth offset
 */
M3G_API M3Gfloat m3gGetDepthOffsetFactor(M3GCompositingMode handle)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    return compositingMode->factor;
}

/*!
 * \brief Get depth offset units.
 *
 * \param handle CompositingMode object
 * \return constant depth offset
 */
M3G_API M3Gfloat m3gGetDepthOffsetUnits(M3GCompositingMode handle)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    return compositingMode->units;
}

/*!
 * \brief Get alpha write enable.
 *
 * \param handle CompositingMode object
 * \retval M3G_TRUE alpha write enabled
 * \retval M3G_FALSE alpha write disabled
 */
M3G_API M3Gbool m3gIsAlphaWriteEnabled(M3GCompositingMode handle)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    return compositingMode->alphaWrite;
}

/*!
 * \brief Get color write enable.
 *
 * \param handle CompositingMode object
 * \retval M3G_TRUE color write enabled
 * \retval M3G_FALSE color  write disabled
 */
M3G_API M3Gbool m3gIsColorWriteEnabled(M3GCompositingMode handle)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    return compositingMode->colorWrite;
}

/*!
 * \brief Get depth test enable.
 *
 * \param handle CompositingMode object
 * \retval M3G_TRUE depth test enabled
 * \retval M3G_FALSE depth test disabled
 */
M3G_API M3Gbool m3gIsDepthTestEnabled(M3GCompositingMode handle)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    return compositingMode->depthTest;
}

/*!
 * \brief Get depth write enable.
 *
 * \param handle CompositingMode object
 * \retval M3G_TRUE depth write enabled
 * \retval M3G_FALSE depth write disabled
 */
M3G_API M3Gbool m3gIsDepthWriteEnabled(M3GCompositingMode handle)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    return compositingMode->depthWrite;
}

/*!
 * \brief Set alpha write enable.
 *
 * \param handle CompositingMode object
 * \param enable alpha write enable
 */
M3G_API void m3gSetAlphaWriteEnable(M3GCompositingMode handle, M3Gbool enable)
{
    CompositingMode *compositingMode = (CompositingMode*)handle;
    M3G_VALIDATE_OBJECT(compositingMode);
    compositingMode->alphaWrite = (GLboolean) enable;
}