graphicscomposition/openwfcompositionengine/composition/src/wfcapi.c
author Faisal Memon <faisal.memon@nokia.com>
Fri, 25 Jun 2010 17:49:58 +0100
branchEGL_MERGE
changeset 105 158b2308cc08
parent 0 5d03bc08d59c
child 110 7f25ef56562d
child 141 f5b6a43d0d2d
child 163 bbf46f59e123
permissions -rw-r--r--
Fix def files so that the implementation agnostic interface definition has no non-standards defined entry points, and change the eglrefimpl specific implementation to place its private entry points high up in the ordinal order space in the implementation region, not the standards based entrypoints region.

/* Copyright (c) 2009 The Khronos Group Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and/or associated documentation files (the
 * "Materials"), to deal in the Materials without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Materials, and to
 * permit persons to whom the Materials are furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Materials.
 *
 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 */

/*! \ingroup wfc
 *  \file wfcapi.c
 *  \brief OpenWF Composition SI, API implementation.
 *
 *  For function documentations, see OpenWF Composition specification 1.0
 *
 *  The general layout of an API function is:
 *  - grab API mutex (lock API)
 *  - check parameter validity
 *  - invoke implementation function (WFD_...)
 *  - unlock API
 *  - return
 *
 */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <WF/wfc.h>
#include <WF/wfcext.h>

#include "wfcstructs.h"
#include "wfccontext.h"
#include "owfnativestream.h"
#include "owfscreen.h"

#define RGB_NUM_BYTES       (sizeof(WFCuint8) * 4)

#define COND_FAIL(cond,error,retval) \
    if (!(cond)) { \
        WFC_Device_SetError(dev, error); \
        WFC_Unlock(); \
        return retval; \
    }

#define COND_FAIL_NR(cond,error) \
    if (!(cond)) { \
        WFC_Device_SetError(dev, error); \
        WFC_Unlock(); \
        return; \
    }

#define GET_DEVICE(d, h, x) \
    WFC_Lock(); \
    d = WFC_Device_FindByHandle(h); \
    if (NULL == d) { \
        WFC_Unlock(); \
        return x; \
    }

#define GET_DEVICE_NR(d, h) \
    WFC_Lock(); \
    d = WFC_Device_FindByHandle(h); \
    if (WFC_INVALID_HANDLE == d) { \
        WFC_Unlock(); \
        return; \
    }

#define GET_CONTEXT_NR(c,d,h) \
    c = WFC_Device_FindContext(d, h); \
    if (WFC_INVALID_HANDLE == c) { \
        WFC_Device_SetError((d)->handle, WFC_ERROR_BAD_HANDLE); \
        WFC_Unlock(); \
        return; \
    }

#define GET_CONTEXT(c,d,h,x) \
    c = WFC_Device_FindContext(d, h); \
    if (WFC_INVALID_HANDLE == c) { \
        WFC_Device_SetError((d)->handle, WFC_ERROR_BAD_HANDLE); \
        WFC_Unlock(); \
        return x; \
    }

#define SUCCEED(retval) \
    WFC_Device_SetError(dev, WFC_ERROR_NONE); \
    WFC_Unlock(); \
    return retval

#define SUCCEED_NR() \
    WFC_Device_SetError(dev, WFC_ERROR_NONE); \
    WFC_Unlock(); \
    return

#define FAIL(err, retval) \
    WFC_Device_SetError(dev, err); \
    WFC_Unlock(); \
    return retval

#define FAIL_NR(err) \
    WFC_Device_SetError(dev, err); \
    WFC_Unlock(); \
    return


static OWF_MUTEX           mutex;

static void WFC_Cleanup()
{
    OWF_Mutex_Destroy(&mutex);
}

static void WFC_Lock()
{
    if (!mutex)
    {
        OWF_Mutex_Init(&mutex);
        xatexit(WFC_Cleanup);   // Use adaptation version of atexit
    }
    OWF_Mutex_Lock(&mutex);
}

static void WFC_Unlock()
{
    OWF_Mutex_Unlock(&mutex);
}

/*=========================================================================*/
/*  4. DEVICE                                                              */
/*=========================================================================*/

WFC_API_CALL WFCint WFC_APIENTRY
wfcEnumerateDevices(WFCint *deviceIds,
                    WFCint deviceIdsCount,
                    const WFCint *filterList)
{
    WFCint                  n;

    /* populate list with device IDs */
    n = WFC_Devices_GetIds(deviceIds, deviceIdsCount, filterList);
    return n;
}

WFC_API_CALL WFCDevice WFC_APIENTRY
wfcCreateDevice(WFCint deviceId, const WFCint *attribList)
{
    WFCDevice               device;

    /* currently only empty attribute list or NULL is allowed */
    if (attribList && *attribList != WFC_NONE)
    {

        return WFC_INVALID_HANDLE;
    }
    WFC_Lock();
    device = WFC_Device_Create(deviceId);
    WFC_Unlock();

    return device;
}

WFC_API_CALL WFCErrorCode WFC_APIENTRY
wfcDestroyDevice(WFCDevice dev)
{
    WFC_DEVICE*             device;
    WFCErrorCode            result = WFC_ERROR_BAD_DEVICE;

    DPRINT(("wfcDestroyDevice(%d)", dev));

    WFC_Lock();
    device = WFC_Device_FindByHandle(dev);
    if (device)
    {
        WFC_Device_Destroy(device);
        result = WFC_ERROR_NONE;
    }
    WFC_Unlock();
    return result;
}

WFC_API_CALL WFCint WFC_APIENTRY
wfcGetDeviceAttribi(WFCDevice dev,
                    WFCDeviceAttrib attrib)
{
    WFC_DEVICE*             device;
    WFCint                  result = 0;
    WFCErrorCode            err;

    GET_DEVICE(device, dev, 0);
    err = WFC_Device_GetAttribi(device, attrib, &result);

    FAIL(err, result);
}

WFC_API_CALL WFCErrorCode WFC_APIENTRY
wfcGetError(WFCDevice dev)
{
    WFC_DEVICE* device;
    WFCErrorCode            err;

    GET_DEVICE(device, dev, WFC_ERROR_BAD_DEVICE);

    err = WFC_Device_GetError(device);
    WFC_Unlock();
    return err;
}

WFC_API_CALL void WFC_APIENTRY
wfcCommit(WFCDevice dev, WFCContext ctx, WFCboolean wait)
{
    WFC_DEVICE*             device;
    WFC_CONTEXT*            context;
    WFCErrorCode            error;

    DPRINT(("wfcCommit(%d,%d,%d)", dev, ctx, wait));
    GET_DEVICE_NR(device, dev);
    GET_CONTEXT_NR(context, device, ctx);

    error = WFC_Context_InvokeCommit(device, context, wait);

    FAIL_NR(error);
}

/*=========================================================================*/
/* 5. CONTEXT                                                              */
/*=========================================================================*/

WFC_API_CALL WFCContext WFC_APIENTRY
wfcCreateOnScreenContext(WFCDevice dev,
                         WFCint screenNumber,
                         const WFCint* attribList)
{
    WFC_CONTEXT*            context = NULL;
    WFC_DEVICE*             device = NULL;

    GET_DEVICE(device, dev, WFC_INVALID_HANDLE);

    /* currently only empty attribute list or NULL is allowed */
    COND_FAIL(!(attribList && *attribList != WFC_NONE),
              WFC_ERROR_BAD_ATTRIBUTE,
              WFC_INVALID_HANDLE);

    if (screenNumber == WFC_DEFAULT_SCREEN_NUMBER)
    {
        screenNumber = OWF_Screen_GetDefaultNumber();
    }
    else
    {
        /* check screen number validity */
        if (!OWF_Screen_Valid(screenNumber))
        {
            FAIL(WFC_ERROR_UNSUPPORTED, WFC_INVALID_HANDLE);
        }
    }

    /* check that no other context currently uses this screen */
    if (!OWF_Screen_Valid_And_Available(screenNumber))
    {
        FAIL(WFC_ERROR_IN_USE, WFC_INVALID_HANDLE);
    }


    context = WFC_Device_CreateContext(device,
                                       WFC_INVALID_HANDLE,
                                       WFC_CONTEXT_TYPE_ON_SCREEN,
                                       screenNumber);
    if (!context)
    {
        FAIL(WFC_ERROR_OUT_OF_MEMORY, WFC_INVALID_HANDLE);
    }

    SUCCEED(context->handle);
}

WFC_API_CALL WFCContext WFC_APIENTRY
wfcCreateOffScreenContext(WFCDevice dev,
                          WFCNativeStreamType stream,
                          const WFCint *attribList)
{
    WFC_CONTEXT*            context = NULL;
    WFC_DEVICE*             device = NULL;
    OWFNativeStreamType 	internalStream=OWF_INVALID_HANDLE;
    OWF_STREAM_ERROR 		streamError;
    
    GET_DEVICE(device, dev, WFC_INVALID_HANDLE);

    /* currently only empty attribute list or NULL is allowed */
    COND_FAIL(!(attribList && *attribList != WFC_NONE),
              WFC_ERROR_BAD_ATTRIBUTE,
              WFC_INVALID_HANDLE);

    COND_FAIL(OWF_INVALID_HANDLE != (OWFNativeStreamType) stream,
              WFC_ERROR_ILLEGAL_ARGUMENT,
              WFC_INVALID_HANDLE);
    internalStream=owfNativeStreamFromWFC(stream,&streamError);
    COND_FAIL(OWF_STREAM_ERROR_INVALID_STREAM!=streamError,WFC_ERROR_UNSUPPORTED,WFC_INVALID_HANDLE);
    COND_FAIL(OWF_STREAM_ERROR_OUT_OF_MEMORY!=streamError,WFC_ERROR_OUT_OF_MEMORY,WFC_INVALID_HANDLE);
    
    if (!WFC_Context_IsValidTargetStream(internalStream))
    {
        owfNativeStreamDestroy(internalStream); /*cancel owfNativeStreamFromWFC reference increase*/
        FAIL(WFC_ERROR_UNSUPPORTED,WFC_INVALID_HANDLE);
    }
    context = WFC_Device_CreateContext(device, internalStream,
                                       WFC_CONTEXT_TYPE_OFF_SCREEN,
                                       OWF_RESERVED_BAD_SCREEN_NUMBER);
    owfNativeStreamDestroy(internalStream);	/*cancel owfNativeStreamFromWFC reference increase*/
    COND_FAIL(NULL != context, WFC_ERROR_OUT_OF_MEMORY, WFC_INVALID_HANDLE);

    SUCCEED(context->handle);
}

WFC_API_CALL void WFC_APIENTRY
wfcDestroyContext(WFCDevice dev,
                  WFCContext ctx)
{
    WFC_DEVICE*             device = NULL;
    WFCErrorCode            err;

    DPRINT(("wfcDestroyContext(%d, %d)", dev, ctx));
    GET_DEVICE_NR(device, dev);

    err = WFC_Device_DestroyContext(device, ctx);
    FAIL_NR(err);
}

WFC_API_CALL WFCint WFC_APIENTRY
wfcGetContextAttribi(WFCDevice dev,
                     WFCContext ctx,
                     WFCContextAttrib attrib)
{
    WFC_CONTEXT*            context = NULL;
    WFC_DEVICE*             device = NULL;
    WFCint                  value = 0;
    WFCErrorCode            err;

    GET_DEVICE(device, dev, 0);
    GET_CONTEXT(context, device, ctx, 0);

    err = WFC_Context_GetAttribi(context, attrib, &value);

    FAIL(err, value);
}

WFC_API_CALL void WFC_APIENTRY
wfcSetContextAttribi(WFCDevice dev,
                     WFCContext ctx,
                     WFCContextAttrib attrib,
                     WFCint value)
{
    WFC_DEVICE*             device;
    WFC_CONTEXT*            context;
    WFCErrorCode            err;

    GET_DEVICE_NR(device, dev);
    GET_CONTEXT_NR(context, device, ctx);

    err = WFC_Context_SetAttribi(context, attrib, value);
    FAIL_NR(err);
}

WFC_API_CALL void WFC_APIENTRY
wfcGetContextAttribfv(WFCDevice dev,
                      WFCContext ctx,
                      WFCContextAttrib attrib,
                      WFCint count,
                      WFCfloat *values) WFC_APIEXIT
{
    WFC_DEVICE*             device;
    WFC_CONTEXT*            context;
    WFCErrorCode            err;

    GET_DEVICE_NR(device, dev);
    GET_CONTEXT_NR(context, device, ctx);

    err = WFC_Context_GetAttribfv(context, attrib, count, values);
    FAIL_NR(err);
}

WFC_API_CALL void WFC_APIENTRY
wfcSetContextAttribfv(WFCDevice dev,
                      WFCContext ctx,
                      WFCContextAttrib attrib,
                      WFCint count,
                      const WFCfloat *values) WFC_APIEXIT
{
      WFC_DEVICE*             device;
      WFC_CONTEXT*            context;
      WFCErrorCode            err;

      GET_DEVICE_NR(device, dev);
      GET_CONTEXT_NR(context, device, ctx);

      err = WFC_Context_SetAttribfv(context, attrib, count, values);
      FAIL_NR(err);
}

/*=========================================================================*/
/* 6. IMAGE PROVIDERS (SOURCES & MASKS)                                    */
/*=========================================================================*/

WFC_API_CALL WFCSource WFC_APIENTRY
wfcCreateSourceFromStream(WFCDevice dev,
                          WFCContext ctx,
                          WFCNativeStreamType stream,
                          const WFCint *attribList)
{
    WFC_DEVICE*             device;
    WFC_IMAGE_PROVIDER*     source;
    WFC_CONTEXT*            context;
    OWFNativeStreamType 	internalStream=OWF_INVALID_HANDLE;
    OWF_STREAM_ERROR 		streamError;

    GET_DEVICE(device, dev, WFC_INVALID_HANDLE);

    /* currently only empty attribute list or NULL is allowed */
    COND_FAIL(!(attribList && *attribList != WFC_NONE),
              WFC_ERROR_BAD_ATTRIBUTE,
              WFC_INVALID_HANDLE);

    GET_CONTEXT(context, device, ctx, WFC_INVALID_HANDLE);
    COND_FAIL(OWF_INVALID_HANDLE != (OWFNativeStreamType) stream,
              WFC_ERROR_ILLEGAL_ARGUMENT,
              WFC_INVALID_HANDLE);

    internalStream=owfNativeStreamFromWFC(stream,&streamError);
    COND_FAIL(OWF_STREAM_ERROR_INVALID_STREAM!=streamError,WFC_ERROR_UNSUPPORTED,WFC_INVALID_HANDLE);
    COND_FAIL(OWF_STREAM_ERROR_OUT_OF_MEMORY!=streamError,WFC_ERROR_OUT_OF_MEMORY,WFC_INVALID_HANDLE);

    if (context->stream == internalStream)
    	{
    	owfNativeStreamDestroy(internalStream);
        FAIL( WFC_ERROR_IN_USE, WFC_INVALID_HANDLE);
    	}
    
    if (!WFC_Context_IsValidSourceStream(internalStream))
        {
        owfNativeStreamDestroy(internalStream);
        FAIL( WFC_ERROR_UNSUPPORTED, WFC_INVALID_HANDLE);
        }

    source = WFC_Device_CreateSource(device, context, internalStream);
    owfNativeStreamDestroy(internalStream);	/*cancel FromWFC reference increase*/
    COND_FAIL(NULL != source, WFC_ERROR_OUT_OF_MEMORY, WFC_INVALID_HANDLE);

    SUCCEED(source->handle);
}

WFC_API_CALL void WFC_APIENTRY
wfcDestroySource(WFCDevice dev,
                 WFCSource src)
{
    WFC_DEVICE*             device;
    WFCErrorCode            err;

    GET_DEVICE_NR(device, dev);

    err = WFC_Device_DestroySource(device, src);

    FAIL_NR(err);
}

WFC_API_CALL WFCMask WFC_APIENTRY
wfcCreateMaskFromStream(WFCDevice dev,
                        WFCContext ctx,
                        WFCNativeStreamType stream,
                        const WFCint *attribList) WFC_APIEXIT
{
    WFC_DEVICE*             device;
    WFC_CONTEXT*            context;
    WFC_IMAGE_PROVIDER*     mask;
    WFCboolean              inUse;
    OWFNativeStreamType 	internalStream=OWF_INVALID_HANDLE;
    OWF_STREAM_ERROR 		streamError;


    GET_DEVICE(device, dev, WFC_ERROR_BAD_DEVICE);

    /* currently only empty attribute list or NULL is allowed */
    COND_FAIL(!(attribList && *attribList != WFC_NONE),
              WFC_ERROR_BAD_ATTRIBUTE,
              WFC_INVALID_HANDLE);

    GET_CONTEXT(context, device, ctx, WFC_INVALID_HANDLE);
    COND_FAIL(OWF_INVALID_HANDLE != (OWFNativeStreamType) stream,
              WFC_ERROR_ILLEGAL_ARGUMENT,
              WFC_INVALID_HANDLE);

    internalStream=owfNativeStreamFromWFC(stream,&streamError);
    COND_FAIL(OWF_STREAM_ERROR_INVALID_STREAM!=streamError,WFC_ERROR_UNSUPPORTED,WFC_INVALID_HANDLE);
    COND_FAIL(OWF_STREAM_ERROR_OUT_OF_MEMORY!=streamError,WFC_ERROR_OUT_OF_MEMORY,WFC_INVALID_HANDLE);

    inUse = WFC_Device_StreamIsTarget(device, internalStream);
    if (inUse)
    	{
       	owfNativeStreamDestroy(internalStream);
        FAIL( WFC_ERROR_IN_USE, WFC_INVALID_HANDLE);
       	}

    mask = WFC_Device_CreateMask(device, context, internalStream);
    owfNativeStreamDestroy(internalStream);	/*cancel FromWFC reference increase*/
    COND_FAIL(NULL != mask, WFC_ERROR_OUT_OF_MEMORY, WFC_INVALID_HANDLE);

    SUCCEED(mask->handle);
}

WFC_API_CALL void WFC_APIENTRY
wfcDestroyMask(WFCDevice dev,
               WFCMask mask) WFC_APIEXIT
{
    WFC_DEVICE*             device;
    WFCErrorCode            error;

    GET_DEVICE_NR(device, dev);

    error = WFC_Device_DestroyMask(device, mask);

    FAIL_NR(error);
}

/*=========================================================================*/
/* 7. COMPOSITION ELEMENTS                                                 */
/*=========================================================================*/

WFC_API_CALL WFCElement WFC_APIENTRY
wfcCreateElement(WFCDevice dev,
                 WFCContext ctx,
                 const WFCint* attribList) WFC_APIEXIT
{
    WFC_DEVICE*             device;
    WFC_ELEMENT*            element;
    WFC_CONTEXT*            context;

    GET_DEVICE(device, dev, WFC_INVALID_HANDLE);

    /* currently only empty attribute list or NULL is allowed */
    COND_FAIL(!(attribList && *attribList != WFC_NONE),
              WFC_ERROR_BAD_ATTRIBUTE,
              WFC_INVALID_HANDLE);

    GET_CONTEXT(context, device, ctx, WFC_INVALID_HANDLE);

    element = WFC_Device_CreateElement(device, context);
    COND_FAIL(NULL != element, WFC_ERROR_OUT_OF_MEMORY, WFC_INVALID_HANDLE);

    SUCCEED(element->handle);
}

WFC_API_CALL void WFC_APIENTRY
wfcDestroyElement(WFCDevice dev,
                  WFCElement element) WFC_APIEXIT
{
    WFC_DEVICE*             device;
    WFCErrorCode            error = WFC_ERROR_BAD_HANDLE;

    GET_DEVICE_NR(device, dev);

    error = WFC_Device_DestroyElement(device, element);

    FAIL_NR(error);
}

#define ATTR_FUNC_PROLOGUE  \
    WFCErrorCode            error; \
    WFC_DEVICE*             device; \
    \
    GET_DEVICE(device, dev, 0)

#define ATTR_FUNC_PROLOGUE_NR  \
    WFCErrorCode            error; \
    WFC_DEVICE*             device; \
    \
    GET_DEVICE_NR(device, dev)

#define ATTR_FUNC_EPILOGUE(x) \
    FAIL(error, x)

#define ATTR_FUNC_EPILOGUE_NR \
    FAIL_NR(error)

WFC_API_CALL WFCint WFC_APIENTRY
wfcGetElementAttribi(WFCDevice dev,
                     WFCElement element,
                     WFCElementAttrib attrib) WFC_APIEXIT
{
    WFCint                  value;

    ATTR_FUNC_PROLOGUE;

    error = WFC_Device_GetElementAttribiv(device, element, attrib, 1, &value);

    ATTR_FUNC_EPILOGUE(value);
}

WFC_API_CALL WFCfloat WFC_APIENTRY
wfcGetElementAttribf(WFCDevice dev,
                     WFCElement element,
                     WFCElementAttrib attrib) WFC_APIEXIT
{
    WFCfloat                value;

    ATTR_FUNC_PROLOGUE;

    COND_FAIL(WFC_ELEMENT_GLOBAL_ALPHA == attrib,
              WFC_ERROR_BAD_ATTRIBUTE,
              0.0f);

    error = WFC_Device_GetElementAttribfv(device, element, attrib, 1, &value);

    /* value is [0, OWF_ALPHA_MAX_VALUE], map to [0, 1] */
    value = value / OWF_ALPHA_MAX_VALUE;

    ATTR_FUNC_EPILOGUE(value);
}

WFC_API_CALL void WFC_APIENTRY
wfcGetElementAttribiv(WFCDevice dev,
                      WFCElement element,
                      WFCElementAttrib attrib,
                      WFCint count,
                      WFCint *values) WFC_APIEXIT
{
    ATTR_FUNC_PROLOGUE_NR;

    COND_FAIL_NR(WFC_ELEMENT_SOURCE_RECTANGLE == attrib ||
                 WFC_ELEMENT_DESTINATION_RECTANGLE == attrib,
                 WFC_ERROR_BAD_ATTRIBUTE);

    error = WFC_Device_GetElementAttribiv(device, element, attrib, count,
                                          values);
    ATTR_FUNC_EPILOGUE_NR;
}

WFC_API_CALL void WFC_APIENTRY
wfcGetElementAttribfv(WFCDevice dev,
                      WFCElement element,
                      WFCElementAttrib attrib,
                      WFCint count,
                      WFCfloat *values) WFC_APIEXIT
{
    ATTR_FUNC_PROLOGUE_NR;

    COND_FAIL_NR(WFC_ELEMENT_SOURCE_RECTANGLE == attrib ||
                 WFC_ELEMENT_DESTINATION_RECTANGLE == attrib,
                 WFC_ERROR_BAD_ATTRIBUTE);

    error = WFC_Device_GetElementAttribfv(device, element, attrib, count,
                                          values);

    ATTR_FUNC_EPILOGUE_NR;
}

WFC_API_CALL void WFC_APIENTRY
wfcSetElementAttribi(WFCDevice dev,
                     WFCElement element,
                     WFCElementAttrib attrib,
                     WFCint value) WFC_APIEXIT
{
    ATTR_FUNC_PROLOGUE_NR;

    error = WFC_Device_SetElementAttribiv(device, element, attrib, 1, &value);

    ATTR_FUNC_EPILOGUE_NR;
}

WFC_API_CALL void WFC_APIENTRY
wfcSetElementAttribf(WFCDevice dev,
                     WFCElement element,
                     WFCElementAttrib attrib,
                     WFCfloat value) WFC_APIEXIT
{
    ATTR_FUNC_PROLOGUE_NR;

    COND_FAIL_NR(WFC_ELEMENT_GLOBAL_ALPHA == attrib,
                 WFC_ERROR_BAD_ATTRIBUTE);

    error = WFC_Device_SetElementAttribfv(device, element, attrib, 1, &value);

    ATTR_FUNC_EPILOGUE_NR;
}

WFC_API_CALL void WFC_APIENTRY
wfcSetElementAttribiv(WFCDevice dev,
                      WFCElement element,
                      WFCElementAttrib attrib,
                      WFCint count,
                      const WFCint *values) WFC_APIEXIT
{
    ATTR_FUNC_PROLOGUE_NR;

    COND_FAIL_NR(WFC_ELEMENT_SOURCE_RECTANGLE == attrib ||
                 WFC_ELEMENT_DESTINATION_RECTANGLE == attrib,
                 WFC_ERROR_BAD_ATTRIBUTE);

    error = WFC_Device_SetElementAttribiv(device, element, attrib, count,
                                          values);

    ATTR_FUNC_EPILOGUE_NR;
}

WFC_API_CALL void WFC_APIENTRY
wfcSetElementAttribfv(WFCDevice dev,
                      WFCElement element,
                      WFCElementAttrib attrib,
                      WFCint count,
                      const WFCfloat *values) WFC_APIEXIT
{
    ATTR_FUNC_PROLOGUE_NR;

    COND_FAIL_NR(WFC_ELEMENT_SOURCE_RECTANGLE == attrib ||
                 WFC_ELEMENT_DESTINATION_RECTANGLE == attrib,
                 WFC_ERROR_BAD_ATTRIBUTE);

    error = WFC_Device_SetElementAttribfv(device, element, attrib, count,
                                          values);

    ATTR_FUNC_EPILOGUE_NR;
}

WFC_API_CALL void WFC_APIENTRY
wfcInsertElement(WFCDevice dev,
                 WFCElement element,
                 WFCElement subordinate) WFC_APIEXIT
{
    WFC_DEVICE*             device;
    WFC_ELEMENT*            elemento;
    WFCErrorCode            error;

    GET_DEVICE_NR(device, dev);

    /*
    - element is inserted immediately above subordinate
    - if subordinate is NULL, then element will go to bottom
    - both elements must be in the same scene (context)
    */
    elemento = WFC_Device_FindElement(device, element);
    COND_FAIL_NR(WFC_INVALID_HANDLE != elemento, WFC_ERROR_BAD_HANDLE);

    error = WFC_Context_InsertElement(CONTEXT(elemento->context),
                                      element,
                                      subordinate);

    FAIL_NR(error);
}

WFC_API_CALL void WFC_APIENTRY
wfcRemoveElement(WFCDevice dev,
                 WFCElement element) WFC_APIEXIT
{
    WFC_DEVICE*             device;
    WFC_ELEMENT*            elemento;
    WFCErrorCode            error;

    GET_DEVICE_NR(device, dev);

    elemento = WFC_Device_FindElement(device, element);
    COND_FAIL_NR(WFC_INVALID_HANDLE != elemento, WFC_ERROR_BAD_HANDLE);

    error = WFC_Context_RemoveElement(CONTEXT(elemento->context), element);

    FAIL_NR(error);
}

WFC_API_CALL WFCElement WFC_APIENTRY
wfcGetElementAbove(WFCDevice dev, WFCElement element) WFC_APIEXIT
{
    WFC_DEVICE*             device = NULL;
    WFC_ELEMENT*            elemento = NULL;
    WFCElement              result = WFC_INVALID_HANDLE;
    WFCErrorCode            error = WFC_ERROR_NONE;

    GET_DEVICE(device, dev, WFC_INVALID_HANDLE);

    elemento = WFC_Device_FindElement(device, element);
    COND_FAIL(WFC_INVALID_HANDLE != elemento,
              WFC_ERROR_BAD_HANDLE,
              WFC_INVALID_HANDLE);

    error = WFC_Context_GetElementAbove(CONTEXT(elemento->context),
                                        element,
                                        &result);

    FAIL(error, result);
}

WFC_API_CALL WFCElement WFC_APIENTRY
wfcGetElementBelow(WFCDevice dev, WFCElement element) WFC_APIEXIT
{
    WFC_DEVICE*             device = NULL;
    WFC_ELEMENT*            elemento = NULL;
    WFCElement              result = WFC_INVALID_HANDLE;
    WFCErrorCode            error = WFC_ERROR_NONE;

    GET_DEVICE(device, dev, WFC_INVALID_HANDLE);

    elemento = WFC_Device_FindElement(device, element);
    COND_FAIL(WFC_INVALID_HANDLE != elemento,
              WFC_ERROR_BAD_HANDLE,
              WFC_INVALID_HANDLE);

    error = WFC_Context_GetElementBelow(CONTEXT(elemento->context),
                                        element,
                                        &result);

    FAIL(error, result);
}

/*=========================================================================*/
/* 8. RENDERING                                                            */
/*=========================================================================*/

WFC_API_CALL void WFC_APIENTRY
wfcActivate(WFCDevice dev,
            WFCContext ctx) WFC_APIEXIT
{
    WFC_DEVICE*             device;
    WFC_CONTEXT*            context;

    GET_DEVICE_NR(device, dev);
    GET_CONTEXT_NR(context, device, ctx);

    WFC_Context_Activate(context, WFC_TRUE);

    SUCCEED_NR();
}

WFC_API_CALL void WFC_APIENTRY
wfcDeactivate(WFCDevice dev,
              WFCContext ctx) WFC_APIEXIT
{
    WFC_DEVICE*             device;
    WFC_CONTEXT*            context;

    GET_DEVICE_NR(device, dev);
    GET_CONTEXT_NR(context, device, ctx);

    WFC_Context_Activate(context, WFC_FALSE);

    SUCCEED_NR();
}

WFC_API_CALL void WFC_APIENTRY
wfcCompose(WFCDevice dev,
           WFCContext ctx,
           WFCboolean wait) WFC_APIEXIT
{
    WFC_DEVICE*             device;
    WFC_CONTEXT*            context;
    WFCboolean              able;

    GET_DEVICE_NR(device, dev);
    GET_CONTEXT_NR(context, device, ctx);

    /* context must not be active */
    COND_FAIL_NR(!WFC_Context_Active(context), WFC_ERROR_UNSUPPORTED);

    /* send composition request */
    able = WFC_Context_InvokeComposition(device, context, wait);
    COND_FAIL_NR(WFC_TRUE == able, WFC_ERROR_BUSY);

    SUCCEED_NR();
}


/*=========================================================================*/
/* 9. SYNCHRONIZATION                                                      */
/*=========================================================================*/

WFC_API_CALL void WFC_APIENTRY
wfcFence(WFCDevice dev,
         WFCContext ctx,
         WFCEGLDisplay dpy,
         WFCEGLSync sync)
{
    WFC_DEVICE*     device;
    WFC_CONTEXT*    context;

    DPRINT(("wfcFence(%08x,%08x,%08x)", dev, ctx, sync));

    GET_DEVICE_NR(device, dev);
    DPRINT(("  device = %p", device));

    GET_CONTEXT_NR(context, device, ctx);
    DPRINT(("  context = %p", context));
    
    /* unsignal sync object first */
    OWF_ASSERT(context->eglPrivateSignalSync);
    if ( !(context->eglPrivateSignalSync((EGLDisplay)dpy, sync, EGL_UNSIGNALED_KHR)) )
    {
        FAIL_NR(WFC_ERROR_ILLEGAL_ARGUMENT);
    }

    /* insert fence 'token' to command stream */
    WFC_Context_InsertFence(context, dpy, sync);
    SUCCEED_NR();
}

/*=========================================================================*/
/* 10. EXTENSION SUPPORT                                                   */
/*=========================================================================*/

WFC_API_CALL WFCint WFC_APIENTRY
wfcGetStrings(WFCDevice dev,
              WFCStringID name,
              const char **strings,
              WFCint stringsCount) WFC_APIEXIT
{
    WFC_DEVICE*             pDevice;
    const char**            tmp;
    WFCint                  retVal;

    GET_DEVICE(pDevice, dev, 0);
    COND_FAIL(stringsCount >= 0, WFC_ERROR_ILLEGAL_ARGUMENT, 0);

    switch (name)
    {
    case WFC_VENDOR:
        retVal = 1;
        tmp = &wfc_strings[WFC_VENDOR_INDEX];
        break;

    case WFC_RENDERER:
        retVal = 1;
        tmp = &wfc_strings[WFC_RENDERER_INDEX];
        break;

    case WFC_VERSION:
        retVal = 1;
        tmp = &wfc_strings[WFC_VERSION_INDEX];
        break;

    case WFC_EXTENSIONS:
        tmp = &wfc_extensions[0];
        for (retVal=0; tmp[retVal] != NULL; retVal++)
        {
            /* get extensions array size */
        }
        break;

    default:
        FAIL(WFC_ERROR_ILLEGAL_ARGUMENT, 0);
    }

    if (strings != NULL)
    {
        WFCint i;

        if (stringsCount < retVal)
        {
            retVal = stringsCount;
        }
        for (i=0; i<retVal; i++)
        {
            strings[i] = tmp[i];
        }
    }

    SUCCEED(retVal);
}

WFC_API_CALL WFCboolean WFC_APIENTRY
wfcIsExtensionSupported(WFCDevice dev,
                        const char *string) WFC_APIEXIT
{
    WFC_DEVICE* pDevice;
    WFCint i;
    WFCboolean retVal = WFC_FALSE;

    GET_DEVICE(pDevice, dev, retVal);
    /* Bad param does not update device error state */
    COND_FAIL(string,WFC_ERROR_NONE,retVal);
    
    for (i=0; wfc_extensions[i] != NULL; i++)
    {
       if (strcmp(string, wfc_extensions[i])==0)
       {
           retVal = WFC_TRUE;
           break;
       }
    }

    SUCCEED(retVal);
}

/*=========================================================================*/
/* 11. TEST ONLY API FOR ON SCREEN IMAGE EXPORTING                         */
/*=========================================================================*/

WFC_API_CALL WFCNativeStreamType WFC_APIENTRY
wfcGetOnScreenStream(WFCDevice dev, WFCContext ctx) WFC_APIEXIT
{
	WFC_DEVICE*             device;
	WFC_CONTEXT*            context;

	GET_DEVICE(device, dev, WFC_INVALID_HANDLE);
	DPRINT(("  device = %p", device));

	GET_CONTEXT(context, device, ctx, WFC_INVALID_HANDLE);
	DPRINT(("  context = %p", context));

	/* Protect context's target stream from being destroyed by the user
	 * WFC_CONTEXT_Dtor will reset this flag. */
	owfNativeStreamSetProtectionFlag(context->stream, OWF_TRUE);

	SUCCEED(context->stream);
}