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 wfcelement.c
*
* \brief SI Element handling
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <WF/wfc.h>
#include "wfcelement.h"
#include "wfccontext.h"
#include "wfcdevice.h"
#include "wfcstructs.h"
#include "wfcimageprovider.h"
#include "owfnativestream.h"
#include "owfattributes.h"
#include "owfmemory.h"
#include "owfobject.h"
#include "owfdebug.h"
#ifdef __cplusplus
extern "C" {
#endif
#define FIRST_ELEMENT_HANDLE 3000
#define FAIL_IF(c,e) if (c) { return e; }
static const WFCbitfield validTransparencyModes[] = {
WFC_TRANSPARENCY_NONE,
WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA,
WFC_TRANSPARENCY_SOURCE,
WFC_TRANSPARENCY_MASK,
WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA |
WFC_TRANSPARENCY_SOURCE,
WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA |
WFC_TRANSPARENCY_MASK
};
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
void
WFC_Element_Initialize(WFC_ELEMENT* element)
{
element->dstRect[0] = 0;
element->dstRect[1] = 0;
element->dstRect[2] = 0;
element->dstRect[3] = 0;
element->srcRect[0] = 0;
element->srcRect[1] = 0;
element->srcRect[2] = 0;
element->srcRect[3] = 0;
element->source = WFC_INVALID_HANDLE;
element->sourceFlip = WFC_FALSE;
element->sourceRotation = WFC_ROTATION_0;
element->sourceScaleFilter = WFC_SCALE_FILTER_NONE;
element->transparencyTypes = 0;
element->globalAlpha = OWF_ALPHA_MAX_VALUE;
element->maskHandle = WFC_INVALID_HANDLE;
element->sourceHandle = WFC_INVALID_HANDLE;
}
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
OWF_API_CALL void
WFC_Element_Destroy(WFC_ELEMENT* element)
{
if (element)
{
DPRINT(("WFC_Element_Destroy"));
DPRINT((" element = %p (%d)", element, element->handle));
DESTROY(element->cachedSource);
DESTROY(element->cachedMask);
DPRINT((" cachedSource = %p (%d)", element->cachedSource,
element->cachedSource ?
element->cachedSource->handle :
0));
DPRINT((" cachedMask = %p (%d)", element->cachedMask,
element->cachedMask ?
element->cachedMask->handle :
0));
DESTROY(element->source);
DESTROY(element->mask);
DPRINT((" source = %p (%d)", element->source,
element->source ?
element->source->handle :
0));
DPRINT((" mask = %p (%d)", element->mask,
element->mask ?
element->mask->handle :
0));
DESTROY(element->context);
OWF_Pool_PutObject(element);
}
}
/*---------------------------------------------------------------------------
* Create new element into context
*
* \param context Context into which to create the element
*
* \return New element object or NULL
*----------------------------------------------------------------------------*/
OWF_API_CALL WFC_ELEMENT*
WFC_Element_Create(WFC_CONTEXT* context)
{
static WFCint nextElementHandle = FIRST_ELEMENT_HANDLE;
WFC_ELEMENT* element;
element = (WFC_ELEMENT*)OWF_Pool_GetObject(context->elementPool);
if (element)
{
WFC_Element_Initialize(element);
element->handle = nextElementHandle++;
ADDREF(element->context, context);
element->device = context->device;
}
return element;
}
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
OWF_API_CALL WFC_ELEMENT*
WFC_Element_Clone(WFC_ELEMENT* element)
{
WFC_ELEMENT* clone;
WFC_CONTEXT* context;
OWF_ASSERT(element);
DPRINT(("WFC_Element_Clone: element = %d, context = %d", element->handle,
element->context->handle));
context = CONTEXT(element->context);
clone = (WFC_ELEMENT*)OWF_Pool_GetObject(context->elementPool);
if (clone)
{
WFC_Element_Initialize(clone);
clone->handle = element->handle;
clone->sourceFlip = element->sourceFlip;
clone->sourceRotation = element->sourceRotation;
clone->sourceScaleFilter= element->sourceScaleFilter;
clone->transparencyTypes= element->transparencyTypes;
clone->globalAlpha = element->globalAlpha;
clone->maskHandle = element->maskHandle;
clone->sourceHandle = element->sourceHandle;
ADDREF(clone->cachedMask, element->cachedMask);
ADDREF(clone->cachedSource, element->cachedSource);
ADDREF(clone->mask, element->mask);
ADDREF(clone->source, element->source);
clone->device = element->device;
ADDREF(clone->context, element->context);
memcpy(clone->srcRect, element->srcRect, 4 * sizeof(WFCfloat));
memcpy(clone->dstRect, element->dstRect, 4 * sizeof(WFCfloat));
}
return clone;
}
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
static WFCboolean WFC_Element_ClampRectangle(const char* rtype,
WFCfloat* rect)
{
/*
* int -> float conversion:
* ------------------------
*
* above 2^24 we start to lose precision when performing
* conversions between floats & ints, thus we must clamp
* values above in order to avoid nasty sign-change effects
* and other weird side-effects.
*
*/
const WFCfloat LIMIT = 1.6777216E7f;
WFCint i;
WFCboolean clamped = WFC_FALSE;
/* Prevent compiler warning when DPRINT is disabled */
(void) rtype;
for (i = 0; i < 4; i++)
{
if (fabs(rect[i]) > LIMIT)
{
#ifdef DEBUG
static const char* coord[4] = {"x", "y", "width", "height"};
(void)coord[0];
#endif
DPRINT((" Warning: Precision loss in element's %s rectangle's "
"%s coordinate.",
rtype, coord[i]));
rect[i] = rect[i] < 0 ? -LIMIT : LIMIT;
clamped = WFC_TRUE;
}
}
return clamped;
}
/*===========================================================================
*
* Attribute set-time checking functions. These are used for checking
* the attributes before saving them into elements. Attributes are validated
* for 2nd time during commit, where e.g. destination rectangle size vs.
* mask size dependency is checked.
*
*============================================================================*/
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
static WFCErrorCode
WFC_Element_ValidateSourceRectangle(WFC_ELEMENT* element,
WFCfloat* rect)
{
WFCErrorCode result = WFC_ERROR_NONE;
#ifndef DEBUG
(void) element;
#endif
OWF_ASSERT(element);
OWF_ASSERT(rect);
if (rect[0] < 0.0f || rect[1] < 0.0f || rect[2] < 0.0f || rect[3] < 0.0f)
{
result = WFC_ERROR_ILLEGAL_ARGUMENT;
}
else if (WFC_Element_ClampRectangle("source", rect))
{
result = WFC_ERROR_NONE;
}
return result;
}
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
static WFCErrorCode
WFC_Element_ValidateDestinationRectangle(WFC_ELEMENT* element,
WFCfloat* rect)
{
WFCErrorCode result = WFC_ERROR_NONE;
#ifndef DEBUG
(void) element;
#endif
OWF_ASSERT(element);
OWF_ASSERT(rect);
DPRINT(("WFC_Element_ValidateDestinationRectangle(element = %d)",
element->handle));
if (rect[2] < 0.0f || rect[3] < 0.0f)
{
result = WFC_ERROR_ILLEGAL_ARGUMENT;
}
else if (WFC_Element_ClampRectangle("destination", rect))
{
/* ... return error or something here? */
result = WFC_ERROR_NONE;
}
/* Hmm.. let's clamp the rectangle even more! To 16k*16k at max;
* in OWF_Image_Create we calculate the byte size of the image buffer
* required, and if we have 4bpp, we get overflow for pixelcounts
* >= 65536*16384. */
rect[2] = CLAMP(rect[2], 0, 16384);
rect[3] = CLAMP(rect[3], 0, 16384);
return result;
}
#define BOOLEAN_TO_ERROR(x) ((x) ? WFC_ERROR_NONE : WFC_ERROR_ILLEGAL_ARGUMENT)
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
static WFCErrorCode
WFC_Element_ValidateScalarAttributei(WFC_ELEMENT* element,
WFCElementAttrib attrib,
WFCint value)
{
WFCErrorCode result = WFC_ERROR_NONE;
OWF_ASSERT(element);
switch (attrib)
{
case WFC_ELEMENT_SOURCE:
{
WFC_IMAGE_PROVIDER* source;
source = WFC_Device_FindImageProvider(element->device,
value,
WFC_IMAGE_SOURCE);
result = BOOLEAN_TO_ERROR((WFC_INVALID_HANDLE == value) ||
((WFC_INVALID_HANDLE != value) &&
(NULL != source)));
break;
}
case WFC_ELEMENT_MASK:
{
WFC_IMAGE_PROVIDER* mask;
mask = WFC_Device_FindImageProvider(element->device,
value,
WFC_IMAGE_MASK);
result = BOOLEAN_TO_ERROR((WFC_INVALID_HANDLE == value) ||
((WFC_INVALID_HANDLE != value) &&
(NULL != mask)));
break;
}
case WFC_ELEMENT_SOURCE_ROTATION:
{
WFCRotation rotation = (WFCRotation) value;
result = BOOLEAN_TO_ERROR((WFC_ROTATION_0 == rotation ||
WFC_ROTATION_90 == rotation ||
WFC_ROTATION_180 == rotation ||
WFC_ROTATION_270 == rotation));
break;
}
case WFC_ELEMENT_SOURCE_SCALE_FILTER:
{
WFCScaleFilter filter = (WFCScaleFilter) value;
result = BOOLEAN_TO_ERROR((WFC_SCALE_FILTER_NONE == filter ||
WFC_SCALE_FILTER_FASTER == filter ||
WFC_SCALE_FILTER_BETTER == filter));
break;
}
case WFC_ELEMENT_SOURCE_FLIP:
{
WFCboolean flip = (WFCboolean) value;
result = BOOLEAN_TO_ERROR((WFC_TRUE == flip ||
WFC_FALSE == flip));
break;
}
case WFC_ELEMENT_TRANSPARENCY_TYPES:
{
WFCint ii;
WFCint count = sizeof(validTransparencyModes) /
sizeof(WFCbitfield);
WFCbitfield types = (WFCbitfield) value;
result = WFC_ERROR_ILLEGAL_ARGUMENT;
for (ii = 0; ii < count; ii++) {
if (types == validTransparencyModes[ii])
{
result = WFC_ERROR_NONE;
break;
}
}
break;
}
default:
{
result = WFC_ERROR_BAD_ATTRIBUTE;
break;
}
}
return result;
}
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
static WFCErrorCode
WFC_Element_ValidateScalarAttributef(WFC_ELEMENT* element,
WFCElementAttrib attrib,
WFCfloat value)
{
WFCErrorCode result = WFC_ERROR_NONE;
#ifndef DEBUG
(void) element;
#endif
OWF_ASSERT(element);
switch (attrib)
{
case WFC_ELEMENT_GLOBAL_ALPHA:
{
result = BOOLEAN_TO_ERROR(value >= OWF_ALPHA_MIN_VALUE &&
value <= OWF_ALPHA_MAX_VALUE);
break;
}
/* SPECIAL CASES */
case WFC_ELEMENT_SOURCE_FLIP:
case WFC_ELEMENT_SOURCE_ROTATION:
case WFC_ELEMENT_SOURCE_SCALE_FILTER:
case WFC_ELEMENT_TRANSPARENCY_TYPES:
case WFC_ELEMENT_SOURCE:
case WFC_ELEMENT_MASK:
{
/* NOTE! special early out here. */
result = WFC_ERROR_BAD_ATTRIBUTE;
break;
}
default:
{
result = WFC_ERROR_ILLEGAL_ARGUMENT;
break;
}
}
return result;
}
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
static void
WFC_Element_SetElementImageProvider(WFC_ELEMENT* element,
WFC_IMAGE_PROVIDER_TYPE type,
WFCHandle handle)
{
WFC_IMAGE_PROVIDER* provider;
OWF_ASSERT(element);
provider = WFC_Device_FindImageProvider(element->device, handle, type);
switch (type)
{
case WFC_IMAGE_SOURCE:
{
DESTROY(element->cachedSource);
ADDREF(element->cachedSource, provider);
element->sourceHandle = handle;
break;
}
case WFC_IMAGE_MASK:
{
DESTROY(element->cachedMask);
ADDREF(element->cachedMask, provider);
element->maskHandle = handle;
break;
}
}
}
/*---------------------------------------------------------------------------
* \brief Set vector integer attribute for an element
*
* \param element Element
* \param attrib Attribute name
* \param count Attribute size
* \param values Attribute vector value
*
*----------------------------------------------------------------------------*/
OWF_API_CALL WFCErrorCode
WFC_Element_SetAttribiv(WFC_ELEMENT* element,
WFCElementAttrib attrib,
WFCint count,
const WFCint* values)
{
WFCErrorCode result = WFC_ERROR_NONE;
FAIL_IF(NULL == values, WFC_ERROR_ILLEGAL_ARGUMENT);
switch (attrib)
{
/* Vector attributes */
case WFC_ELEMENT_SOURCE_RECTANGLE:
case WFC_ELEMENT_DESTINATION_RECTANGLE:
{
WFCfloat rect[4];
rect[0] = values[0];
rect[1] = values[1];
rect[2] = values[2];
rect[3] = values[3];
result = WFC_Element_SetAttribfv(element, attrib, count, rect);
break;
}
case WFC_ELEMENT_GLOBAL_ALPHA:
{
WFCfloat fvalue = values[0] /
(WFCfloat) OWF_BYTE_MAX_VALUE;
result = WFC_Element_SetAttribfv(element,
attrib,
1,
&fvalue);
break;
}
/* Scalar attributes */
default:
{
WFCint value;
FAIL_IF(1 != count, WFC_ERROR_ILLEGAL_ARGUMENT);
value = values[0];
/* Validate the value thus ensuring it is safe to change it */
result = WFC_Element_ValidateScalarAttributei(element,
attrib,
value);
if (WFC_ERROR_NONE != result)
{
break;
}
switch (attrib)
{
case WFC_ELEMENT_SOURCE:
{
WFC_Element_SetElementImageProvider(element,
WFC_IMAGE_SOURCE,
value);
break;
}
case WFC_ELEMENT_MASK:
{
WFC_Element_SetElementImageProvider(element,
WFC_IMAGE_MASK,
value);
break;
}
case WFC_ELEMENT_SOURCE_FLIP:
{
element->sourceFlip = (WFCboolean)value;
break;
}
case WFC_ELEMENT_SOURCE_ROTATION:
{
element->sourceRotation = (WFCRotation)value;
break;
}
case WFC_ELEMENT_SOURCE_SCALE_FILTER:
{
element->sourceScaleFilter = (WFCScaleFilter)value;
break;
}
case WFC_ELEMENT_TRANSPARENCY_TYPES:
{
element->transparencyTypes = value;
break;
}
default:
{
result = WFC_ERROR_BAD_ATTRIBUTE;
break;
}
}
break;
}
}
return result;
}
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
OWF_API_CALL WFCErrorCode
WFC_Element_SetAttribfv(WFC_ELEMENT* element,
WFCElementAttrib attrib,
WFCint count,
const WFCfloat* values)
{
WFCErrorCode result = WFC_ERROR_NONE;
FAIL_IF(NULL == values, WFC_ERROR_ILLEGAL_ARGUMENT);
switch (attrib)
{
/* Vector attributes */
case WFC_ELEMENT_SOURCE_RECTANGLE:
case WFC_ELEMENT_DESTINATION_RECTANGLE:
{
WFCfloat clamped[4];
FAIL_IF(4 != count, WFC_ERROR_ILLEGAL_ARGUMENT);
memcpy(clamped, values, 4 * sizeof(WFCfloat));
if (WFC_ELEMENT_SOURCE_RECTANGLE == attrib)
{
/* this clamps the rectangle, in case it has values that
* cause precision loss or other fuzzy behaviour. */
result = WFC_Element_ValidateSourceRectangle(element, clamped);
if (WFC_ERROR_NONE == result)
{
memcpy(element->srcRect, clamped, 4 * sizeof(WFCfloat));
DPRINT((" Source rectangle set to (%.2f,%.2f,%.2f,%.2f)",
clamped[0], clamped[1], clamped[2], clamped[3]));
}
else
{
DPRINT((" Source rectangle (%.2f,%.2f,%.2f,%.2f) is " \
"invalid",
values[0], values[1], values[2], values[3]));
}
}
else
{
result = WFC_Element_ValidateDestinationRectangle(element,
clamped);
if (WFC_ERROR_NONE == result)
{
memcpy(element->dstRect, clamped, 4 * sizeof(WFCfloat));
DPRINT((" Destination rectangle set to " \
"(%.2f,%.2f,%.2f,%.2f)",
clamped[0], clamped[1], clamped[2], clamped[3]));
}
else
{
DPRINT((" Destination rectangle (%.2f,%.2f,%.2f,%.2f) is "
"invalid",
values[0], values[1], values[2], values[3]));
}
}
break;
}
/* scalar attributes */
case WFC_ELEMENT_GLOBAL_ALPHA:
{
/* values[0] must be [0, 1] */
WFCfloat value = values[0];
/* value is [0, 1] map to [0, OWF_ALPHA_MAX] */
value = value * OWF_ALPHA_MAX_VALUE;
/* validate the value */
result = WFC_Element_ValidateScalarAttributef(element,
attrib,
value);
if (WFC_ERROR_NONE != result)
{
/* invalid value for attribute, out we go */
break;
}
element->globalAlpha = value;
break;
}
default:
{
result = WFC_ERROR_BAD_ATTRIBUTE;
break;
}
}
return result;
}
/*---------------------------------------------------------------------------
* Attribute getters
*----------------------------------------------------------------------------*/
OWF_API_CALL WFCErrorCode
WFC_Element_GetAttribiv(WFC_ELEMENT* element,
WFCElementAttrib attrib,
WFCint count,
WFCint* values)
{
WFCErrorCode result = WFC_ERROR_NONE;
FAIL_IF(NULL == values, WFC_ERROR_ILLEGAL_ARGUMENT);
switch (attrib)
{
/* Vector attributes */
case WFC_ELEMENT_SOURCE_RECTANGLE:
case WFC_ELEMENT_DESTINATION_RECTANGLE:
{
WFCfloat rect[4] = {0.0, 0.0, 0.0, 0.0};
result = WFC_Element_GetAttribfv(element, attrib, count, rect);
if (WFC_ERROR_NONE == result)
{
values[0] = floor(rect[0]);
values[1] = floor(rect[1]);
values[2] = floor(rect[2]);
values[3] = floor(rect[3]);
}
break;
}
/* Scalar attributes */
default:
{
FAIL_IF(1 != count, WFC_ERROR_ILLEGAL_ARGUMENT);
switch (attrib)
{
/* pure int attributes */
case WFC_ELEMENT_SOURCE:
{
*values = element->sourceHandle;
break;
}
case WFC_ELEMENT_MASK:
{
*values = element->maskHandle;
break;
}
case WFC_ELEMENT_SOURCE_FLIP:
{
*values = element->sourceFlip;
break;
}
case WFC_ELEMENT_SOURCE_ROTATION:
{
*values = element->sourceRotation;
break;
}
case WFC_ELEMENT_SOURCE_SCALE_FILTER:
{
*values = element->sourceScaleFilter;
break;
}
case WFC_ELEMENT_TRANSPARENCY_TYPES:
{
*values = element->transparencyTypes;
break;
}
case WFC_ELEMENT_GLOBAL_ALPHA:
{
WFCfloat fvalue;
WFC_Element_GetAttribfv(element, attrib, 1, &fvalue);
*values = floor(OWF_BYTE_MAX_VALUE * fvalue /
OWF_ALPHA_MAX_VALUE);
break;
}
default:
{
result = WFC_ERROR_BAD_ATTRIBUTE;
break;
}
}
break;
}
}
return result;
}
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
OWF_API_CALL WFCErrorCode
WFC_Element_GetAttribfv(WFC_ELEMENT* element,
WFCElementAttrib attrib,
WFCint count,
WFCfloat* values)
{
WFCErrorCode result = WFC_ERROR_NONE;
FAIL_IF(NULL == values, WFC_ERROR_ILLEGAL_ARGUMENT);
switch (attrib)
{
/* Vector attributes */
case WFC_ELEMENT_SOURCE_RECTANGLE:
case WFC_ELEMENT_DESTINATION_RECTANGLE:
{
FAIL_IF(4 != count, WFC_ERROR_ILLEGAL_ARGUMENT);
if (WFC_ELEMENT_SOURCE_RECTANGLE == attrib)
{
values[0] = element->srcRect[0];
values[1] = element->srcRect[1];
values[2] = element->srcRect[2];
values[3] = element->srcRect[3];
}
else
{
values[0] = element->dstRect[0];
values[1] = element->dstRect[1];
values[2] = element->dstRect[2];
values[3] = element->dstRect[3];
}
break;
}
/* Scalar attributes */
default:
{
switch (attrib)
{
case WFC_ELEMENT_GLOBAL_ALPHA:
{
*values = element->globalAlpha;
break;
}
default:
{
result = WFC_ERROR_BAD_ATTRIBUTE;
break;
}
}
break;
}
}
return result;
}
/*---------------------------------------------------------------------------
* Attribute checkers to use during commit to check element
* for inconsistencies.
*----------------------------------------------------------------------------*/
static WFCboolean
WFC_Element_CheckAttribute(WFC_ELEMENT* element,
WFCElementAttrib attrib)
{
#define VALIDATE_SCALAR_I(v) \
(WFC_Element_ValidateScalarAttributei(element, attrib, v) == \
WFC_ERROR_NONE ? WFC_TRUE : WFC_FALSE)
#define VALIDATE_SCALAR_F(v) \
(WFC_Element_ValidateScalarAttributef(element, attrib, v) == \
WFC_ERROR_NONE ? WFC_TRUE : WFC_FALSE)
WFCboolean result = WFC_TRUE;
DPRINT(("WFC_Element_CheckAttribute(%08x,%0x)",
element, attrib));
switch (attrib)
{
/*
INTEGER-ATTRIBUTES
*/
case WFC_ELEMENT_SOURCE:
{
/* Validated when the attribute was modified */
break;
}
case WFC_ELEMENT_MASK:
{
/* Validated when the attribute was modified */
break;
}
case WFC_ELEMENT_SOURCE_FLIP:
{
result = VALIDATE_SCALAR_I(element->sourceFlip) ? WFC_TRUE: WFC_FALSE;
if (!result)
{
DPRINT((" Element source flipping is invalid (%d)",
element->sourceFlip));
}
break;
}
case WFC_ELEMENT_SOURCE_ROTATION:
{
result = VALIDATE_SCALAR_I(element->sourceRotation) ? WFC_TRUE: WFC_FALSE;
if (!result)
{
DPRINT((" Element source rotation is invalid (%d)",
element->sourceRotation));
}
break;
}
case WFC_ELEMENT_SOURCE_SCALE_FILTER:
{
result = VALIDATE_SCALAR_I(element->sourceScaleFilter) ? WFC_TRUE: WFC_FALSE;
if (!result)
{
DPRINT((" Element source scale filter is invalid (%d)",
element->sourceScaleFilter));
}
break;
}
case WFC_ELEMENT_TRANSPARENCY_TYPES:
{
result = VALIDATE_SCALAR_I(element->transparencyTypes) ? WFC_TRUE: WFC_FALSE;
if (!result)
{
DPRINT((" Element transparency type is invalid (%x)",
element->transparencyTypes));
}
break;
}
case WFC_ELEMENT_GLOBAL_ALPHA:
{
result = VALIDATE_SCALAR_F(element->globalAlpha) ? WFC_TRUE: WFC_FALSE;
if (!result)
{
DPRINT((" Element global alpha is invalid (%d)",
element->globalAlpha));
}
break;
}
case WFC_ELEMENT_DESTINATION_RECTANGLE:
{
WFC_IMAGE_PROVIDER* mask;
/* The <0 test is repeated in SetAttribfv ValidateDestinationRectangle */
if (element->dstRect[2] < 0 || element->dstRect[3] < 0)
{
DPRINT((" Element destination rectangle has negative "
"width/height"));
result = WFC_FALSE;
break;
}
if (element->maskHandle!=WFC_INVALID_HANDLE)
{
result = WFC_Element_CheckAttribute(element, WFC_ELEMENT_MASK);
if (result)
{
mask = WFC_Device_FindMask(element->device,
element->maskHandle);
if (!mask)
{
DPRINT((" Mask handle is valid, but mask object now destroyed"));
mask=element->cachedMask;
if (!mask)
{
mask=element->mask;
}
}
if (mask)
{
WFCint maskWidth, maskHeight;
DPRINT((" Element has a mask"));
/* if the element has a mask, then width & height must match
the dimensions of that mask */
owfNativeStreamGetHeader(mask->streamHandle,&maskWidth, &maskHeight,NULL,NULL,NULL);
if (element->dstRect[2] != maskWidth ||
element->dstRect[3] != maskHeight)
{
DPRINT((" Mask size (%dx%d) != element size (%d,%d)",
maskWidth, maskHeight,
(int)element->dstRect[2],
(int)element->dstRect[3]));
result = WFC_FALSE;
break;
}
}
else
{
DPRINT((" No mask pointers could be opened! Scene not safe!"));
result = WFC_FALSE;
}
}
}
break;
}
case WFC_ELEMENT_SOURCE_RECTANGLE:
{
WFC_IMAGE_PROVIDER* source;
result = WFC_Element_CheckAttribute(element, WFC_ELEMENT_SOURCE);
if (result && element->sourceHandle!=WFC_INVALID_HANDLE)
{ /* no source is valid - the element "will not affect composition results" */
source = WFC_Device_FindImageProvider(element->device,
element->sourceHandle,
WFC_IMAGE_SOURCE);
result = WFC_TRUE;
if (!source)
{
DPRINT((" Source handle is valid, but source object now destroyed"));
source=element->cachedSource;
if (!source)
{
source=element->source;
}
}
if (source)
{
WFCint sourceWidth, sourceHeight;
owfNativeStreamGetHeader(source->streamHandle,&sourceWidth, &sourceHeight,NULL,NULL,NULL);
/* The <0 test is repeated in SetAttribfv ValidateSourceRectangle */
if ((element->srcRect[0] < 0) ||
(element->srcRect[1] < 0) ||
(element->srcRect[2] < 0) ||
(element->srcRect[3] < 0) ||
(element->srcRect[0] + element->srcRect[2]) > sourceWidth ||
(element->srcRect[1] + element->srcRect[3]) > sourceHeight)
{
DPRINT((" Source rectangle out of bounds"));
DPRINT((" (%f,%f,%f,%f), source size %dx%d",
element->srcRect[0], element->srcRect[1],
element->srcRect[2], element->srcRect[3],
sourceWidth, sourceHeight));
result = WFC_FALSE;
break;
}
}
else
{
DPRINT((" No source pointers could be opened! Scene not safe!"));
result = WFC_FALSE;
}
}
break;
}
case WFC_ELEMENT_FORCE_32BIT:
{
/* to keep compiler happy */
OWF_ASSERT(0);
break;
}
}
return result;
#undef VALIDATE_SCALAR_F
#undef VALIDATE_SCALAR_I
}
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
OWF_API_CALL WFCboolean
WFC_Element_HasConflicts(WFC_ELEMENT* element)
{
#define CHECK(x) \
if (!WFC_Element_CheckAttribute(element, x)) \
{\
DPRINT(("Element %d: Conflict in attribute %08x", element->handle, x));\
return WFC_TRUE; \
}
CHECK(WFC_ELEMENT_SOURCE);
CHECK(WFC_ELEMENT_MASK);
CHECK(WFC_ELEMENT_SOURCE_RECTANGLE);
CHECK(WFC_ELEMENT_DESTINATION_RECTANGLE);
CHECK(WFC_ELEMENT_SOURCE_FLIP);
CHECK(WFC_ELEMENT_SOURCE_ROTATION);
CHECK(WFC_ELEMENT_SOURCE_SCALE_FILTER);
CHECK(WFC_ELEMENT_TRANSPARENCY_TYPES);
CHECK(WFC_ELEMENT_GLOBAL_ALPHA);
#undef CHECK
/* all ok, no conflicts */
return WFC_FALSE;
}
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
OWF_API_CALL WFCboolean
WFC_Element_AffectsCompositionResults(WFC_ELEMENT* element)
{
if ( (element->transparencyTypes&WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA)
&& element->globalAlpha==OWF_FULLY_TRANSPARENT )
{
return WFC_FALSE;
}
if (element->sourceHandle==WFC_INVALID_HANDLE)
{
return WFC_FALSE;
}
if (element->dstRect[2]==0.0f || element->dstRect[3]==0.0f)
{
return WFC_FALSE;
}
if (element->srcRect[2]==0.0f || element->srcRect[3]==0.0f)
{
return WFC_FALSE;
}
return WFC_TRUE;
}
/*---------------------------------------------------------------------------
*
*----------------------------------------------------------------------------*/
OWF_API_CALL void
WFC_Element_Commit(WFC_ELEMENT* element)
{
OWF_ASSERT(element);
DPRINT(("WFC_Element_Commit(element = %d)\n", element->handle));
/* replace source/mask ONLY if it has changed. without these checks,
* both source and mask would be overwritten whenever one of them
* is changed.
*/
if (element->cachedSource != element->source)
{
element->source = element->cachedSource;
}
if (element->cachedMask != element->mask)
{
element->mask = element->cachedMask;
}
/* these must be reset now that the element is committed -- the only purpose
* of these cached ones is to have source/mask object pointers in the
* element so that source/mask can be safely deleted from the device even
* if that particular image provider is set as source/mask for some element
* that is not yet committed.
*/
DPRINT((" Prior to destroying cached objects:"));
DPRINT((" R(cachedMask) = %d", REFCOUNT(element->cachedMask)));
DPRINT((" R(cachedSource) = %d", REFCOUNT(element->cachedSource)));
element->cachedSource = NULL;
element->cachedMask = NULL;
DPRINT((" new source = %d\n", element->source ?
element->source->handle : 0));
DPRINT((" new mask = %d\n", element->mask ?
element->mask->handle : 0));
}
#ifdef __cplusplus
}
#endif