diff -r 000000000000 -r 5d03bc08d59c graphicscomposition/openwfcompositionengine/composition/src/wfcelement.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graphicscomposition/openwfcompositionengine/composition/src/wfcelement.c Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,1207 @@ +/* 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 +#include +#include +#include + +#include + +#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 +