os/graphics/graphicscomposition/openwfcompositionengine/composition/src/wfcelement.c
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/graphicscomposition/openwfcompositionengine/composition/src/wfcelement.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1207 @@
1.4 +/* Copyright (c) 2009-2010 The Khronos Group Inc.
1.5 + * Portions copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies)
1.6 + *
1.7 + * Permission is hereby granted, free of charge, to any person obtaining a
1.8 + * copy of this software and/or associated documentation files (the
1.9 + * "Materials"), to deal in the Materials without restriction, including
1.10 + * without limitation the rights to use, copy, modify, merge, publish,
1.11 + * distribute, sublicense, and/or sell copies of the Materials, and to
1.12 + * permit persons to whom the Materials are furnished to do so, subject to
1.13 + * the following conditions:
1.14 + *
1.15 + * The above copyright notice and this permission notice shall be included
1.16 + * in all copies or substantial portions of the Materials.
1.17 + *
1.18 + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1.19 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1.20 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1.21 + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1.22 + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1.23 + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1.24 + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
1.25 + */
1.26 +/*! \ingroup wfc
1.27 + * \file wfcelement.c
1.28 + *
1.29 + * \brief SI Element handling
1.30 + */
1.31 +#include <stdio.h>
1.32 +#include <stdlib.h>
1.33 +#include <math.h>
1.34 +#include <string.h>
1.35 +
1.36 +#include <WF/wfc.h>
1.37 +
1.38 +#include "wfcelement.h"
1.39 +#include "wfccontext.h"
1.40 +#include "wfcdevice.h"
1.41 +#include "wfcstructs.h"
1.42 +#include "wfcimageprovider.h"
1.43 +#include "owfnativestream.h"
1.44 +#include "owfattributes.h"
1.45 +#include "owfmemory.h"
1.46 +#include "owfobject.h"
1.47 +
1.48 +#include "owfdebug.h"
1.49 +
1.50 +#ifdef __cplusplus
1.51 +extern "C" {
1.52 +#endif
1.53 +
1.54 +#define FIRST_ELEMENT_HANDLE 3000
1.55 +
1.56 +#define FAIL_IF(c,e) if (c) { return e; }
1.57 +
1.58 +
1.59 +static const WFCbitfield validTransparencyModes[] = {
1.60 + WFC_TRANSPARENCY_NONE,
1.61 + WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA,
1.62 + WFC_TRANSPARENCY_SOURCE,
1.63 + WFC_TRANSPARENCY_MASK,
1.64 + WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA |
1.65 + WFC_TRANSPARENCY_SOURCE,
1.66 + WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA |
1.67 + WFC_TRANSPARENCY_MASK
1.68 + };
1.69 +
1.70 +/*---------------------------------------------------------------------------
1.71 + *
1.72 + *----------------------------------------------------------------------------*/
1.73 +void
1.74 +WFC_Element_Initialize(WFC_ELEMENT* element)
1.75 +{
1.76 + element->dstRect[0] = 0;
1.77 + element->dstRect[1] = 0;
1.78 + element->dstRect[2] = 0;
1.79 + element->dstRect[3] = 0;
1.80 + element->srcRect[0] = 0;
1.81 + element->srcRect[1] = 0;
1.82 + element->srcRect[2] = 0;
1.83 + element->srcRect[3] = 0;
1.84 +
1.85 + element->source = WFC_INVALID_HANDLE;
1.86 + element->sourceFlip = WFC_FALSE;
1.87 + element->sourceRotation = WFC_ROTATION_0;
1.88 + element->sourceScaleFilter = WFC_SCALE_FILTER_NONE;
1.89 + element->transparencyTypes = 0;
1.90 + element->globalAlpha = OWF_ALPHA_MAX_VALUE;
1.91 + element->maskHandle = WFC_INVALID_HANDLE;
1.92 + element->sourceHandle = WFC_INVALID_HANDLE;
1.93 +}
1.94 +
1.95 +/*---------------------------------------------------------------------------
1.96 + *
1.97 + *----------------------------------------------------------------------------*/
1.98 +OWF_API_CALL void
1.99 +WFC_Element_Destroy(WFC_ELEMENT* element)
1.100 +{
1.101 + if (element)
1.102 + {
1.103 + DPRINT(("WFC_Element_Destroy"));
1.104 +
1.105 + DPRINT((" element = %p (%d)", element, element->handle));
1.106 +
1.107 + DESTROY(element->cachedSource);
1.108 + DESTROY(element->cachedMask);
1.109 +
1.110 + DPRINT((" cachedSource = %p (%d)", element->cachedSource,
1.111 + element->cachedSource ?
1.112 + element->cachedSource->handle :
1.113 + 0));
1.114 + DPRINT((" cachedMask = %p (%d)", element->cachedMask,
1.115 + element->cachedMask ?
1.116 + element->cachedMask->handle :
1.117 + 0));
1.118 +
1.119 + DESTROY(element->source);
1.120 + DESTROY(element->mask);
1.121 +
1.122 + DPRINT((" source = %p (%d)", element->source,
1.123 + element->source ?
1.124 + element->source->handle :
1.125 + 0));
1.126 + DPRINT((" mask = %p (%d)", element->mask,
1.127 + element->mask ?
1.128 + element->mask->handle :
1.129 + 0));
1.130 + DESTROY(element->context);
1.131 +
1.132 + OWF_Pool_PutObject(element);
1.133 + }
1.134 +}
1.135 +
1.136 +/*---------------------------------------------------------------------------
1.137 + * Create new element into context
1.138 + *
1.139 + * \param context Context into which to create the element
1.140 + *
1.141 + * \return New element object or NULL
1.142 + *----------------------------------------------------------------------------*/
1.143 +OWF_API_CALL WFC_ELEMENT*
1.144 +WFC_Element_Create(WFC_CONTEXT* context)
1.145 +{
1.146 + static WFCint nextElementHandle = FIRST_ELEMENT_HANDLE;
1.147 + WFC_ELEMENT* element;
1.148 +
1.149 + OWF_ASSERT(context);
1.150 +
1.151 + element = (WFC_ELEMENT*)OWF_Pool_GetObject(context->elementPool);
1.152 +
1.153 + if (element)
1.154 + {
1.155 + WFC_Element_Initialize(element);
1.156 +
1.157 + element->handle = nextElementHandle++;
1.158 +
1.159 + ADDREF(element->context, context);
1.160 + element->device = context->device;
1.161 + }
1.162 + return element;
1.163 +}
1.164 +
1.165 +/*---------------------------------------------------------------------------
1.166 + *
1.167 + *----------------------------------------------------------------------------*/
1.168 +OWF_API_CALL WFC_ELEMENT*
1.169 +WFC_Element_Clone(WFC_ELEMENT* element)
1.170 +{
1.171 + WFC_ELEMENT* clone;
1.172 + WFC_CONTEXT* context;
1.173 +
1.174 + OWF_ASSERT(element);
1.175 +
1.176 + DPRINT(("WFC_Element_Clone: element = %d, context = %d", element->handle,
1.177 + element->context->handle));
1.178 +
1.179 + context = CONTEXT(element->context);
1.180 + clone = (WFC_ELEMENT*)OWF_Pool_GetObject(context->elementPool);
1.181 +
1.182 + if (clone)
1.183 + {
1.184 + WFC_Element_Initialize(clone);
1.185 +
1.186 + clone->handle = element->handle;
1.187 +
1.188 + clone->sourceFlip = element->sourceFlip;
1.189 + clone->sourceRotation = element->sourceRotation;
1.190 + clone->sourceScaleFilter= element->sourceScaleFilter;
1.191 + clone->transparencyTypes= element->transparencyTypes;
1.192 + clone->globalAlpha = element->globalAlpha;
1.193 + clone->maskHandle = element->maskHandle;
1.194 + clone->sourceHandle = element->sourceHandle;
1.195 +
1.196 + ADDREF(clone->cachedMask, element->cachedMask);
1.197 + ADDREF(clone->cachedSource, element->cachedSource);
1.198 +
1.199 + ADDREF(clone->mask, element->mask);
1.200 + ADDREF(clone->source, element->source);
1.201 + clone->device = element->device;
1.202 +
1.203 + ADDREF(clone->context, element->context);
1.204 +
1.205 + memcpy(clone->srcRect, element->srcRect, 4 * sizeof(WFCfloat));
1.206 + memcpy(clone->dstRect, element->dstRect, 4 * sizeof(WFCfloat));
1.207 +
1.208 + }
1.209 +
1.210 + return clone;
1.211 +}
1.212 +
1.213 +/*---------------------------------------------------------------------------
1.214 + *
1.215 + *----------------------------------------------------------------------------*/
1.216 +static WFCboolean WFC_Element_ClampRectangle(const char* rtype,
1.217 + WFCfloat* rect)
1.218 +{
1.219 + /*
1.220 + * int -> float conversion:
1.221 + * ------------------------
1.222 + *
1.223 + * above 2^24 we start to lose precision when performing
1.224 + * conversions between floats & ints, thus we must clamp
1.225 + * values above in order to avoid nasty sign-change effects
1.226 + * and other weird side-effects.
1.227 + *
1.228 + */
1.229 +
1.230 + const WFCfloat LIMIT = 1.6777216E7f;
1.231 + WFCint i;
1.232 + WFCboolean clamped = WFC_FALSE;
1.233 +
1.234 + /* Prevent compiler warning when DPRINT is disabled */
1.235 + (void) rtype;
1.236 +
1.237 + for (i = 0; i < 4; i++)
1.238 + {
1.239 + if (fabs(rect[i]) > LIMIT)
1.240 + {
1.241 +#ifdef DEBUG
1.242 + static const char* coord[4] = {"x", "y", "width", "height"};
1.243 + (void)coord[0];
1.244 +#endif
1.245 +
1.246 + DPRINT((" Warning: Precision loss in element's %s rectangle's "
1.247 + "%s coordinate.",
1.248 + rtype, coord[i]));
1.249 +
1.250 + rect[i] = rect[i] < 0 ? -LIMIT : LIMIT;
1.251 +
1.252 + clamped = WFC_TRUE;
1.253 + }
1.254 + }
1.255 + return clamped;
1.256 +}
1.257 +/*===========================================================================
1.258 + *
1.259 + * Attribute set-time checking functions. These are used for checking
1.260 + * the attributes before saving them into elements. Attributes are validated
1.261 + * for 2nd time during commit, where e.g. destination rectangle size vs.
1.262 + * mask size dependency is checked.
1.263 + *
1.264 + *============================================================================*/
1.265 +
1.266 +/*---------------------------------------------------------------------------
1.267 + *
1.268 + *----------------------------------------------------------------------------*/
1.269 +static WFCErrorCode
1.270 +WFC_Element_ValidateSourceRectangle(WFC_ELEMENT* element,
1.271 + WFCfloat* rect)
1.272 +{
1.273 + WFCErrorCode result = WFC_ERROR_NONE;
1.274 +
1.275 +#ifndef DEBUG
1.276 + (void) element;
1.277 +#endif
1.278 +
1.279 + OWF_ASSERT(element);
1.280 + OWF_ASSERT(rect);
1.281 +
1.282 + if (rect[0] < 0.0f || rect[1] < 0.0f || rect[2] < 0.0f || rect[3] < 0.0f)
1.283 + {
1.284 + result = WFC_ERROR_ILLEGAL_ARGUMENT;
1.285 + }
1.286 + else if (WFC_Element_ClampRectangle("source", rect))
1.287 + {
1.288 + result = WFC_ERROR_NONE;
1.289 + }
1.290 + return result;
1.291 +}
1.292 +
1.293 +/*---------------------------------------------------------------------------
1.294 + *
1.295 + *----------------------------------------------------------------------------*/
1.296 +static WFCErrorCode
1.297 +WFC_Element_ValidateDestinationRectangle(WFC_ELEMENT* element,
1.298 + WFCfloat* rect)
1.299 +{
1.300 + WFCErrorCode result = WFC_ERROR_NONE;
1.301 +
1.302 +#ifndef DEBUG
1.303 + (void) element;
1.304 +#endif
1.305 +
1.306 + OWF_ASSERT(element);
1.307 + OWF_ASSERT(rect);
1.308 +
1.309 + DPRINT(("WFC_Element_ValidateDestinationRectangle(element = %d)",
1.310 + element->handle));
1.311 +
1.312 + if (rect[2] < 0.0f || rect[3] < 0.0f)
1.313 + {
1.314 + result = WFC_ERROR_ILLEGAL_ARGUMENT;
1.315 + }
1.316 + else if (WFC_Element_ClampRectangle("destination", rect))
1.317 + {
1.318 + /* ... return error or something here? */
1.319 + result = WFC_ERROR_NONE;
1.320 + }
1.321 +
1.322 + /* Hmm.. let's clamp the rectangle even more! To 16k*16k at max;
1.323 + * in OWF_Image_Create we calculate the byte size of the image buffer
1.324 + * required, and if we have 4bpp, we get overflow for pixelcounts
1.325 + * >= 65536*16384. */
1.326 + rect[2] = CLAMP(rect[2], 0, 16384);
1.327 + rect[3] = CLAMP(rect[3], 0, 16384);
1.328 +
1.329 + return result;
1.330 +}
1.331 +
1.332 +#define BOOLEAN_TO_ERROR(x) ((x) ? WFC_ERROR_NONE : WFC_ERROR_ILLEGAL_ARGUMENT)
1.333 +
1.334 +/*---------------------------------------------------------------------------
1.335 + *
1.336 + *----------------------------------------------------------------------------*/
1.337 +static WFCErrorCode
1.338 +WFC_Element_ValidateScalarAttributei(WFC_ELEMENT* element,
1.339 + WFCElementAttrib attrib,
1.340 + WFCint value)
1.341 +{
1.342 + WFCErrorCode result = WFC_ERROR_NONE;
1.343 +
1.344 + OWF_ASSERT(element);
1.345 +
1.346 + switch (attrib)
1.347 + {
1.348 + case WFC_ELEMENT_SOURCE:
1.349 + {
1.350 + WFC_IMAGE_PROVIDER* source;
1.351 +
1.352 + source = WFC_Device_FindImageProvider(element->device,
1.353 + value,
1.354 + WFC_IMAGE_SOURCE);
1.355 +
1.356 + result = BOOLEAN_TO_ERROR((WFC_INVALID_HANDLE == value) ||
1.357 + ((WFC_INVALID_HANDLE != value) &&
1.358 + (NULL != source)));
1.359 + break;
1.360 + }
1.361 +
1.362 + case WFC_ELEMENT_MASK:
1.363 + {
1.364 + WFC_IMAGE_PROVIDER* mask;
1.365 +
1.366 + mask = WFC_Device_FindImageProvider(element->device,
1.367 + value,
1.368 + WFC_IMAGE_MASK);
1.369 +
1.370 + result = BOOLEAN_TO_ERROR((WFC_INVALID_HANDLE == value) ||
1.371 + ((WFC_INVALID_HANDLE != value) &&
1.372 + (NULL != mask)));
1.373 + break;
1.374 + }
1.375 +
1.376 + case WFC_ELEMENT_SOURCE_ROTATION:
1.377 + {
1.378 + WFCRotation rotation = (WFCRotation) value;
1.379 +
1.380 + result = BOOLEAN_TO_ERROR((WFC_ROTATION_0 == rotation ||
1.381 + WFC_ROTATION_90 == rotation ||
1.382 + WFC_ROTATION_180 == rotation ||
1.383 + WFC_ROTATION_270 == rotation));
1.384 + break;
1.385 + }
1.386 +
1.387 + case WFC_ELEMENT_SOURCE_SCALE_FILTER:
1.388 + {
1.389 + WFCScaleFilter filter = (WFCScaleFilter) value;
1.390 +
1.391 + result = BOOLEAN_TO_ERROR((WFC_SCALE_FILTER_NONE == filter ||
1.392 + WFC_SCALE_FILTER_FASTER == filter ||
1.393 + WFC_SCALE_FILTER_BETTER == filter));
1.394 + break;
1.395 + }
1.396 +
1.397 + case WFC_ELEMENT_SOURCE_FLIP:
1.398 + {
1.399 + result = WFC_ERROR_NONE;
1.400 + break;
1.401 + }
1.402 +
1.403 + case WFC_ELEMENT_TRANSPARENCY_TYPES:
1.404 + {
1.405 + WFCint ii;
1.406 + WFCint count = sizeof(validTransparencyModes) /
1.407 + sizeof(WFCbitfield);
1.408 + WFCbitfield types = (WFCbitfield) value;
1.409 +
1.410 + result = WFC_ERROR_ILLEGAL_ARGUMENT;
1.411 + for (ii = 0; ii < count; ii++) {
1.412 + if (types == validTransparencyModes[ii])
1.413 + {
1.414 + result = WFC_ERROR_NONE;
1.415 + break;
1.416 + }
1.417 + }
1.418 + break;
1.419 + }
1.420 +
1.421 + default:
1.422 + {
1.423 + result = WFC_ERROR_BAD_ATTRIBUTE;
1.424 + break;
1.425 + }
1.426 + }
1.427 + return result;
1.428 +}
1.429 +
1.430 +/*---------------------------------------------------------------------------
1.431 + *
1.432 + *----------------------------------------------------------------------------*/
1.433 +static WFCErrorCode
1.434 +WFC_Element_ValidateScalarAttributef(WFC_ELEMENT* element,
1.435 + WFCElementAttrib attrib,
1.436 + WFCfloat value)
1.437 +{
1.438 + WFCErrorCode result = WFC_ERROR_NONE;
1.439 +
1.440 +#ifndef DEBUG
1.441 + (void) element;
1.442 +#endif
1.443 +
1.444 + OWF_ASSERT(element);
1.445 +
1.446 + switch (attrib)
1.447 + {
1.448 + case WFC_ELEMENT_GLOBAL_ALPHA:
1.449 + {
1.450 + result = BOOLEAN_TO_ERROR(value >= OWF_ALPHA_MIN_VALUE &&
1.451 + value <= OWF_ALPHA_MAX_VALUE);
1.452 + break;
1.453 + }
1.454 +
1.455 + /* SPECIAL CASES */
1.456 + case WFC_ELEMENT_SOURCE_FLIP:
1.457 + case WFC_ELEMENT_SOURCE_ROTATION:
1.458 + case WFC_ELEMENT_SOURCE_SCALE_FILTER:
1.459 + case WFC_ELEMENT_TRANSPARENCY_TYPES:
1.460 + case WFC_ELEMENT_SOURCE:
1.461 + case WFC_ELEMENT_MASK:
1.462 + {
1.463 + /* NOTE! special early out here. */
1.464 + result = WFC_ERROR_BAD_ATTRIBUTE;
1.465 + break;
1.466 + }
1.467 +
1.468 + default:
1.469 + {
1.470 + result = WFC_ERROR_ILLEGAL_ARGUMENT;
1.471 + break;
1.472 + }
1.473 + }
1.474 +
1.475 + return result;
1.476 +}
1.477 +
1.478 +/*---------------------------------------------------------------------------
1.479 + *
1.480 + *----------------------------------------------------------------------------*/
1.481 +static void
1.482 +WFC_Element_SetElementImageProvider(WFC_ELEMENT* element,
1.483 + WFC_IMAGE_PROVIDER_TYPE type,
1.484 + WFCHandle handle)
1.485 +{
1.486 + WFC_IMAGE_PROVIDER* provider;
1.487 +
1.488 + OWF_ASSERT(element);
1.489 +
1.490 + provider = WFC_Device_FindImageProvider(element->device, handle, type);
1.491 +
1.492 + switch (type)
1.493 + {
1.494 + case WFC_IMAGE_SOURCE:
1.495 + {
1.496 + DESTROY(element->cachedSource);
1.497 + ADDREF(element->cachedSource, provider);
1.498 + element->sourceHandle = handle;
1.499 + break;
1.500 + }
1.501 + case WFC_IMAGE_MASK:
1.502 + {
1.503 + DESTROY(element->cachedMask);
1.504 + ADDREF(element->cachedMask, provider);
1.505 + element->maskHandle = handle;
1.506 + break;
1.507 + }
1.508 + }
1.509 +}
1.510 +
1.511 +/*---------------------------------------------------------------------------
1.512 + * \brief Set vector integer attribute for an element
1.513 + *
1.514 + * \param element Element
1.515 + * \param attrib Attribute name
1.516 + * \param count Attribute size
1.517 + * \param values Attribute vector value
1.518 + *
1.519 + *----------------------------------------------------------------------------*/
1.520 +OWF_API_CALL WFCErrorCode
1.521 +WFC_Element_SetAttribiv(WFC_ELEMENT* element,
1.522 + WFCElementAttrib attrib,
1.523 + WFCint count,
1.524 + const WFCint* values)
1.525 +{
1.526 + WFCErrorCode result = WFC_ERROR_NONE;
1.527 +
1.528 +
1.529 + FAIL_IF(NULL == values, WFC_ERROR_ILLEGAL_ARGUMENT);
1.530 +
1.531 + switch (attrib)
1.532 + {
1.533 + /* Vector attributes */
1.534 + case WFC_ELEMENT_SOURCE_RECTANGLE:
1.535 + case WFC_ELEMENT_DESTINATION_RECTANGLE:
1.536 + {
1.537 + WFCfloat rect[4];
1.538 +
1.539 + rect[0] = values[0];
1.540 + rect[1] = values[1];
1.541 + rect[2] = values[2];
1.542 + rect[3] = values[3];
1.543 +
1.544 + result = WFC_Element_SetAttribfv(element, attrib, count, rect);
1.545 + break;
1.546 + }
1.547 +
1.548 + case WFC_ELEMENT_GLOBAL_ALPHA:
1.549 + {
1.550 + WFCfloat fvalue = values[0] /
1.551 + (WFCfloat) OWF_BYTE_MAX_VALUE;
1.552 +
1.553 + result = WFC_Element_SetAttribfv(element,
1.554 + attrib,
1.555 + 1,
1.556 + &fvalue);
1.557 + break;
1.558 + }
1.559 +
1.560 + /* Scalar attributes */
1.561 + default:
1.562 + {
1.563 + WFCint value;
1.564 +
1.565 + FAIL_IF(1 != count, WFC_ERROR_ILLEGAL_ARGUMENT);
1.566 +
1.567 + value = values[0];
1.568 +
1.569 + /* Validate the value thus ensuring it is safe to change it */
1.570 + result = WFC_Element_ValidateScalarAttributei(element,
1.571 + attrib,
1.572 + value);
1.573 + if (WFC_ERROR_NONE != result)
1.574 + {
1.575 + break;
1.576 + }
1.577 +
1.578 + switch (attrib)
1.579 + {
1.580 + case WFC_ELEMENT_SOURCE:
1.581 + {
1.582 + WFC_Element_SetElementImageProvider(element,
1.583 + WFC_IMAGE_SOURCE,
1.584 + value);
1.585 + break;
1.586 + }
1.587 + case WFC_ELEMENT_MASK:
1.588 + {
1.589 + WFC_Element_SetElementImageProvider(element,
1.590 + WFC_IMAGE_MASK,
1.591 + value);
1.592 + break;
1.593 + }
1.594 + case WFC_ELEMENT_SOURCE_FLIP:
1.595 + {
1.596 + element->sourceFlip = (WFCboolean)value;
1.597 + break;
1.598 + }
1.599 + case WFC_ELEMENT_SOURCE_ROTATION:
1.600 + {
1.601 + element->sourceRotation = (WFCRotation)value;
1.602 + break;
1.603 + }
1.604 + case WFC_ELEMENT_SOURCE_SCALE_FILTER:
1.605 + {
1.606 + element->sourceScaleFilter = (WFCScaleFilter)value;
1.607 + break;
1.608 + }
1.609 + case WFC_ELEMENT_TRANSPARENCY_TYPES:
1.610 + {
1.611 + element->transparencyTypes = value;
1.612 + break;
1.613 + }
1.614 + default:
1.615 + {
1.616 + result = WFC_ERROR_BAD_ATTRIBUTE;
1.617 + break;
1.618 + }
1.619 + }
1.620 + break;
1.621 + }
1.622 + }
1.623 +
1.624 + return result;
1.625 +}
1.626 +
1.627 +/*---------------------------------------------------------------------------
1.628 + *
1.629 + *----------------------------------------------------------------------------*/
1.630 +OWF_API_CALL WFCErrorCode
1.631 +WFC_Element_SetAttribfv(WFC_ELEMENT* element,
1.632 + WFCElementAttrib attrib,
1.633 + WFCint count,
1.634 + const WFCfloat* values)
1.635 +{
1.636 + WFCErrorCode result = WFC_ERROR_NONE;
1.637 +
1.638 + FAIL_IF(NULL == values, WFC_ERROR_ILLEGAL_ARGUMENT);
1.639 +
1.640 + switch (attrib)
1.641 + {
1.642 + /* Vector attributes */
1.643 + case WFC_ELEMENT_SOURCE_RECTANGLE:
1.644 + case WFC_ELEMENT_DESTINATION_RECTANGLE:
1.645 + {
1.646 + WFCfloat clamped[4];
1.647 +
1.648 + FAIL_IF(4 != count, WFC_ERROR_ILLEGAL_ARGUMENT);
1.649 +
1.650 + memcpy(clamped, values, 4 * sizeof(WFCfloat));
1.651 +
1.652 + if (WFC_ELEMENT_SOURCE_RECTANGLE == attrib)
1.653 + {
1.654 + /* this clamps the rectangle, in case it has values that
1.655 + * cause precision loss or other fuzzy behaviour. */
1.656 + result = WFC_Element_ValidateSourceRectangle(element, clamped);
1.657 +
1.658 + if (WFC_ERROR_NONE == result)
1.659 + {
1.660 + memcpy(element->srcRect, clamped, 4 * sizeof(WFCfloat));
1.661 +
1.662 + DPRINT((" Source rectangle set to (%.2f,%.2f,%.2f,%.2f)",
1.663 + clamped[0], clamped[1], clamped[2], clamped[3]));
1.664 + }
1.665 + else
1.666 + {
1.667 + DPRINT((" Source rectangle (%.2f,%.2f,%.2f,%.2f) is " \
1.668 + "invalid",
1.669 + values[0], values[1], values[2], values[3]));
1.670 + }
1.671 + }
1.672 + else
1.673 + {
1.674 + result = WFC_Element_ValidateDestinationRectangle(element,
1.675 + clamped);
1.676 + if (WFC_ERROR_NONE == result)
1.677 + {
1.678 + memcpy(element->dstRect, clamped, 4 * sizeof(WFCfloat));
1.679 +
1.680 + DPRINT((" Destination rectangle set to " \
1.681 + "(%.2f,%.2f,%.2f,%.2f)",
1.682 + clamped[0], clamped[1], clamped[2], clamped[3]));
1.683 + }
1.684 + else
1.685 + {
1.686 + DPRINT((" Destination rectangle (%.2f,%.2f,%.2f,%.2f) is "
1.687 + "invalid",
1.688 + values[0], values[1], values[2], values[3]));
1.689 + }
1.690 + }
1.691 + break;
1.692 + }
1.693 +
1.694 + /* scalar attributes */
1.695 + case WFC_ELEMENT_GLOBAL_ALPHA:
1.696 + {
1.697 + /* values[0] must be [0, 1] */
1.698 + WFCfloat value = values[0];
1.699 +
1.700 + /* value is [0, 1] map to [0, OWF_ALPHA_MAX] */
1.701 + value = value * OWF_ALPHA_MAX_VALUE;
1.702 +
1.703 + /* validate the value */
1.704 + result = WFC_Element_ValidateScalarAttributef(element,
1.705 + attrib,
1.706 + value);
1.707 +
1.708 + if (WFC_ERROR_NONE != result)
1.709 + {
1.710 + /* invalid value for attribute, out we go */
1.711 + break;
1.712 + }
1.713 +
1.714 + element->globalAlpha = value;
1.715 + break;
1.716 + }
1.717 +
1.718 + default:
1.719 + {
1.720 + result = WFC_ERROR_BAD_ATTRIBUTE;
1.721 + break;
1.722 + }
1.723 + }
1.724 +
1.725 + return result;
1.726 +}
1.727 +
1.728 +/*---------------------------------------------------------------------------
1.729 + * Attribute getters
1.730 + *----------------------------------------------------------------------------*/
1.731 +OWF_API_CALL WFCErrorCode
1.732 +WFC_Element_GetAttribiv(WFC_ELEMENT* element,
1.733 + WFCElementAttrib attrib,
1.734 + WFCint count,
1.735 + WFCint* values)
1.736 +{
1.737 + WFCErrorCode result = WFC_ERROR_NONE;
1.738 +
1.739 +
1.740 + FAIL_IF(NULL == values, WFC_ERROR_ILLEGAL_ARGUMENT);
1.741 +
1.742 + switch (attrib)
1.743 + {
1.744 + /* Vector attributes */
1.745 + case WFC_ELEMENT_SOURCE_RECTANGLE:
1.746 + case WFC_ELEMENT_DESTINATION_RECTANGLE:
1.747 + {
1.748 + WFCfloat rect[4] = {0.0, 0.0, 0.0, 0.0};
1.749 +
1.750 + result = WFC_Element_GetAttribfv(element, attrib, count, rect);
1.751 +
1.752 + if (WFC_ERROR_NONE == result)
1.753 + {
1.754 + values[0] = floor(rect[0]);
1.755 + values[1] = floor(rect[1]);
1.756 + values[2] = floor(rect[2]);
1.757 + values[3] = floor(rect[3]);
1.758 + }
1.759 + break;
1.760 + }
1.761 +
1.762 + /* Scalar attributes */
1.763 + default:
1.764 + {
1.765 + FAIL_IF(1 != count, WFC_ERROR_ILLEGAL_ARGUMENT);
1.766 +
1.767 + switch (attrib)
1.768 + {
1.769 + /* pure int attributes */
1.770 + case WFC_ELEMENT_SOURCE:
1.771 + {
1.772 + *values = element->sourceHandle;
1.773 + break;
1.774 + }
1.775 + case WFC_ELEMENT_MASK:
1.776 + {
1.777 + *values = element->maskHandle;
1.778 + break;
1.779 + }
1.780 + case WFC_ELEMENT_SOURCE_FLIP:
1.781 + {
1.782 + *values = element->sourceFlip;
1.783 + break;
1.784 + }
1.785 + case WFC_ELEMENT_SOURCE_ROTATION:
1.786 + {
1.787 + *values = element->sourceRotation;
1.788 + break;
1.789 + }
1.790 + case WFC_ELEMENT_SOURCE_SCALE_FILTER:
1.791 + {
1.792 + *values = element->sourceScaleFilter;
1.793 + break;
1.794 + }
1.795 + case WFC_ELEMENT_TRANSPARENCY_TYPES:
1.796 + {
1.797 + *values = element->transparencyTypes;
1.798 + break;
1.799 + }
1.800 + case WFC_ELEMENT_GLOBAL_ALPHA:
1.801 + {
1.802 + WFCfloat fvalue;
1.803 +
1.804 + WFC_Element_GetAttribfv(element, attrib, 1, &fvalue);
1.805 + *values = floor(OWF_BYTE_MAX_VALUE * fvalue /
1.806 + OWF_ALPHA_MAX_VALUE);
1.807 + break;
1.808 + }
1.809 + default:
1.810 + {
1.811 + result = WFC_ERROR_BAD_ATTRIBUTE;
1.812 + break;
1.813 + }
1.814 + }
1.815 + break;
1.816 + }
1.817 + }
1.818 +
1.819 + return result;
1.820 +}
1.821 +
1.822 +/*---------------------------------------------------------------------------
1.823 + *
1.824 + *----------------------------------------------------------------------------*/
1.825 +OWF_API_CALL WFCErrorCode
1.826 +WFC_Element_GetAttribfv(WFC_ELEMENT* element,
1.827 + WFCElementAttrib attrib,
1.828 + WFCint count,
1.829 + WFCfloat* values)
1.830 +{
1.831 + WFCErrorCode result = WFC_ERROR_NONE;
1.832 +
1.833 + FAIL_IF(NULL == values, WFC_ERROR_ILLEGAL_ARGUMENT);
1.834 +
1.835 + switch (attrib)
1.836 + {
1.837 + /* Vector attributes */
1.838 + case WFC_ELEMENT_SOURCE_RECTANGLE:
1.839 + case WFC_ELEMENT_DESTINATION_RECTANGLE:
1.840 + {
1.841 + FAIL_IF(4 != count, WFC_ERROR_ILLEGAL_ARGUMENT);
1.842 +
1.843 + if (WFC_ELEMENT_SOURCE_RECTANGLE == attrib)
1.844 + {
1.845 + values[0] = element->srcRect[0];
1.846 + values[1] = element->srcRect[1];
1.847 + values[2] = element->srcRect[2];
1.848 + values[3] = element->srcRect[3];
1.849 + }
1.850 + else
1.851 + {
1.852 + values[0] = element->dstRect[0];
1.853 + values[1] = element->dstRect[1];
1.854 + values[2] = element->dstRect[2];
1.855 + values[3] = element->dstRect[3];
1.856 + }
1.857 + break;
1.858 + }
1.859 +
1.860 + /* Scalar attributes */
1.861 + default:
1.862 + {
1.863 + switch (attrib)
1.864 + {
1.865 + case WFC_ELEMENT_GLOBAL_ALPHA:
1.866 + {
1.867 + *values = element->globalAlpha;
1.868 + break;
1.869 + }
1.870 + default:
1.871 + {
1.872 + result = WFC_ERROR_BAD_ATTRIBUTE;
1.873 + break;
1.874 + }
1.875 + }
1.876 + break;
1.877 + }
1.878 + }
1.879 +
1.880 + return result;
1.881 +}
1.882 +
1.883 +/*---------------------------------------------------------------------------
1.884 + * Attribute checkers to use during commit to check element
1.885 + * for inconsistencies.
1.886 + *----------------------------------------------------------------------------*/
1.887 +static WFCboolean
1.888 +WFC_Element_CheckAttribute(WFC_ELEMENT* element,
1.889 + WFCElementAttrib attrib)
1.890 +{
1.891 +#define VALIDATE_SCALAR_I(v) \
1.892 + (WFC_Element_ValidateScalarAttributei(element, attrib, v) == \
1.893 + WFC_ERROR_NONE ? WFC_TRUE : WFC_FALSE)
1.894 +#define VALIDATE_SCALAR_F(v) \
1.895 + (WFC_Element_ValidateScalarAttributef(element, attrib, v) == \
1.896 + WFC_ERROR_NONE ? WFC_TRUE : WFC_FALSE)
1.897 +
1.898 + WFCboolean result = WFC_TRUE;
1.899 +
1.900 + DPRINT(("WFC_Element_CheckAttribute(%08x,%0x)",
1.901 + element, attrib));
1.902 +
1.903 + switch (attrib)
1.904 + {
1.905 + /*
1.906 + INTEGER-ATTRIBUTES
1.907 + */
1.908 + case WFC_ELEMENT_SOURCE:
1.909 + {
1.910 + /* Validated when the attribute was modified */
1.911 + break;
1.912 + }
1.913 +
1.914 + case WFC_ELEMENT_MASK:
1.915 + {
1.916 + /* Validated when the attribute was modified */
1.917 + break;
1.918 + }
1.919 +
1.920 + case WFC_ELEMENT_SOURCE_FLIP:
1.921 + {
1.922 + result = VALIDATE_SCALAR_I(element->sourceFlip) ? WFC_TRUE: WFC_FALSE;
1.923 + if (!result)
1.924 + {
1.925 + DPRINT((" Element source flipping is invalid (%d)",
1.926 + element->sourceFlip));
1.927 + }
1.928 + break;
1.929 + }
1.930 +
1.931 + case WFC_ELEMENT_SOURCE_ROTATION:
1.932 + {
1.933 + result = VALIDATE_SCALAR_I(element->sourceRotation) ? WFC_TRUE: WFC_FALSE;
1.934 +
1.935 + if (!result)
1.936 + {
1.937 + DPRINT((" Element source rotation is invalid (%d)",
1.938 + element->sourceRotation));
1.939 + }
1.940 + break;
1.941 + }
1.942 +
1.943 + case WFC_ELEMENT_SOURCE_SCALE_FILTER:
1.944 + {
1.945 + result = VALIDATE_SCALAR_I(element->sourceScaleFilter) ? WFC_TRUE: WFC_FALSE;
1.946 +
1.947 + if (!result)
1.948 + {
1.949 + DPRINT((" Element source scale filter is invalid (%d)",
1.950 + element->sourceScaleFilter));
1.951 + }
1.952 + break;
1.953 + }
1.954 +
1.955 + case WFC_ELEMENT_TRANSPARENCY_TYPES:
1.956 + {
1.957 + result = VALIDATE_SCALAR_I(element->transparencyTypes) ? WFC_TRUE: WFC_FALSE;
1.958 +
1.959 + if (!result)
1.960 + {
1.961 + DPRINT((" Element transparency type is invalid (%x)",
1.962 + element->transparencyTypes));
1.963 + }
1.964 + break;
1.965 + }
1.966 +
1.967 + case WFC_ELEMENT_GLOBAL_ALPHA:
1.968 + {
1.969 + result = VALIDATE_SCALAR_F(element->globalAlpha) ? WFC_TRUE: WFC_FALSE;
1.970 + if (!result)
1.971 + {
1.972 + DPRINT((" Element global alpha is invalid (%d)",
1.973 + element->globalAlpha));
1.974 + }
1.975 + break;
1.976 + }
1.977 +
1.978 + case WFC_ELEMENT_DESTINATION_RECTANGLE:
1.979 + {
1.980 + WFC_IMAGE_PROVIDER* mask;
1.981 +
1.982 + /* The <0 test is repeated in SetAttribfv ValidateDestinationRectangle */
1.983 + if (element->dstRect[2] < 0 || element->dstRect[3] < 0)
1.984 + {
1.985 + DPRINT((" Element destination rectangle has negative "
1.986 + "width/height"));
1.987 + result = WFC_FALSE;
1.988 + break;
1.989 + }
1.990 + if (element->maskHandle!=WFC_INVALID_HANDLE)
1.991 + {
1.992 + result = WFC_Element_CheckAttribute(element, WFC_ELEMENT_MASK);
1.993 +
1.994 + if (result)
1.995 + {
1.996 + mask = WFC_Device_FindMask(element->device,
1.997 + element->maskHandle);
1.998 + if (!mask)
1.999 + {
1.1000 + DPRINT((" Mask handle is valid, but mask object now destroyed"));
1.1001 + mask=element->cachedMask;
1.1002 + if (!mask)
1.1003 + {
1.1004 + mask=element->mask;
1.1005 + }
1.1006 + }
1.1007 + if (mask)
1.1008 + {
1.1009 + WFCint maskWidth, maskHeight;
1.1010 +
1.1011 + DPRINT((" Element has a mask"));
1.1012 + /* if the element has a mask, then width & height must match
1.1013 + the dimensions of that mask */
1.1014 + owfNativeStreamGetHeader(mask->streamHandle,&maskWidth, &maskHeight,NULL,NULL,NULL);
1.1015 +
1.1016 + if (element->dstRect[2] != maskWidth ||
1.1017 + element->dstRect[3] != maskHeight)
1.1018 + {
1.1019 + DPRINT((" Mask size (%dx%d) != element size (%d,%d)",
1.1020 + maskWidth, maskHeight,
1.1021 + (int)element->dstRect[2],
1.1022 + (int)element->dstRect[3]));
1.1023 + result = WFC_FALSE;
1.1024 + break;
1.1025 + }
1.1026 + }
1.1027 + else
1.1028 + {
1.1029 + DPRINT((" No mask pointers could be opened! Scene not safe!"));
1.1030 + result = WFC_FALSE;
1.1031 + }
1.1032 + }
1.1033 + }
1.1034 + break;
1.1035 + }
1.1036 +
1.1037 + case WFC_ELEMENT_SOURCE_RECTANGLE:
1.1038 + {
1.1039 + WFC_IMAGE_PROVIDER* source;
1.1040 +
1.1041 + result = WFC_Element_CheckAttribute(element, WFC_ELEMENT_SOURCE);
1.1042 +
1.1043 + if (result && element->sourceHandle!=WFC_INVALID_HANDLE)
1.1044 + { /* no source is valid - the element "will not affect composition results" */
1.1045 + source = WFC_Device_FindImageProvider(element->device,
1.1046 + element->sourceHandle,
1.1047 + WFC_IMAGE_SOURCE);
1.1048 +
1.1049 + result = WFC_TRUE;
1.1050 + if (!source)
1.1051 + {
1.1052 + DPRINT((" Source handle is valid, but source object now destroyed"));
1.1053 + source=element->cachedSource;
1.1054 + if (!source)
1.1055 + {
1.1056 + source=element->source;
1.1057 + }
1.1058 + }
1.1059 +
1.1060 + if (source)
1.1061 + {
1.1062 + WFCint sourceWidth, sourceHeight;
1.1063 +
1.1064 + owfNativeStreamGetHeader(source->streamHandle,&sourceWidth, &sourceHeight,NULL,NULL,NULL);
1.1065 + /* The <0 test is repeated in SetAttribfv ValidateSourceRectangle */
1.1066 + if ((element->srcRect[0] < 0) ||
1.1067 + (element->srcRect[1] < 0) ||
1.1068 + (element->srcRect[2] < 0) ||
1.1069 + (element->srcRect[3] < 0) ||
1.1070 + (element->srcRect[0] + element->srcRect[2]) > sourceWidth ||
1.1071 + (element->srcRect[1] + element->srcRect[3]) > sourceHeight)
1.1072 + {
1.1073 + DPRINT((" Source rectangle out of bounds"));
1.1074 + DPRINT((" (%f,%f,%f,%f), source size %dx%d",
1.1075 + element->srcRect[0], element->srcRect[1],
1.1076 + element->srcRect[2], element->srcRect[3],
1.1077 + sourceWidth, sourceHeight));
1.1078 + result = WFC_FALSE;
1.1079 + break;
1.1080 + }
1.1081 + }
1.1082 + else
1.1083 + {
1.1084 + DPRINT((" No source pointers could be opened! Scene not safe!"));
1.1085 + result = WFC_FALSE;
1.1086 + }
1.1087 + }
1.1088 + break;
1.1089 + }
1.1090 +
1.1091 + case WFC_ELEMENT_FORCE_32BIT:
1.1092 + {
1.1093 + /* to keep compiler happy */
1.1094 + OWF_ASSERT(0);
1.1095 + break;
1.1096 + }
1.1097 + }
1.1098 +
1.1099 + return result;
1.1100 +
1.1101 +#undef VALIDATE_SCALAR_F
1.1102 +#undef VALIDATE_SCALAR_I
1.1103 +}
1.1104 +
1.1105 +/*---------------------------------------------------------------------------
1.1106 + *
1.1107 + *----------------------------------------------------------------------------*/
1.1108 +OWF_API_CALL WFCboolean
1.1109 +WFC_Element_HasConflicts(WFC_ELEMENT* element)
1.1110 +{
1.1111 +#define CHECK(x) \
1.1112 + if (!WFC_Element_CheckAttribute(element, x)) \
1.1113 + {\
1.1114 + DPRINT(("Element %d: Conflict in attribute %08x", element->handle, x));\
1.1115 + return WFC_TRUE; \
1.1116 + }
1.1117 +
1.1118 + CHECK(WFC_ELEMENT_SOURCE);
1.1119 + CHECK(WFC_ELEMENT_MASK);
1.1120 + CHECK(WFC_ELEMENT_SOURCE_RECTANGLE);
1.1121 + CHECK(WFC_ELEMENT_DESTINATION_RECTANGLE);
1.1122 + CHECK(WFC_ELEMENT_SOURCE_FLIP);
1.1123 + CHECK(WFC_ELEMENT_SOURCE_ROTATION);
1.1124 + CHECK(WFC_ELEMENT_SOURCE_SCALE_FILTER);
1.1125 + CHECK(WFC_ELEMENT_TRANSPARENCY_TYPES);
1.1126 + CHECK(WFC_ELEMENT_GLOBAL_ALPHA);
1.1127 +
1.1128 +#undef CHECK
1.1129 +
1.1130 + /* all ok, no conflicts */
1.1131 + return WFC_FALSE;
1.1132 +}
1.1133 +
1.1134 +/*---------------------------------------------------------------------------
1.1135 + *
1.1136 + *----------------------------------------------------------------------------*/
1.1137 +OWF_API_CALL WFCboolean
1.1138 +WFC_Element_AffectsCompositionResults(WFC_ELEMENT* element)
1.1139 +{
1.1140 + if ( (element->transparencyTypes&WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA)
1.1141 + && element->globalAlpha==OWF_FULLY_TRANSPARENT )
1.1142 + {
1.1143 + return WFC_FALSE;
1.1144 + }
1.1145 + if (element->sourceHandle==WFC_INVALID_HANDLE)
1.1146 + {
1.1147 + return WFC_FALSE;
1.1148 + }
1.1149 + if (element->dstRect[2]==0.0f || element->dstRect[3]==0.0f)
1.1150 + {
1.1151 + return WFC_FALSE;
1.1152 + }
1.1153 + if (element->srcRect[2]==0.0f || element->srcRect[3]==0.0f)
1.1154 + {
1.1155 + return WFC_FALSE;
1.1156 + }
1.1157 + return WFC_TRUE;
1.1158 +
1.1159 +}
1.1160 +/*---------------------------------------------------------------------------
1.1161 + *
1.1162 + *----------------------------------------------------------------------------*/
1.1163 +OWF_API_CALL void
1.1164 +WFC_Element_Commit(WFC_ELEMENT* element)
1.1165 +{
1.1166 + OWF_ASSERT(element);
1.1167 +
1.1168 + DPRINT(("WFC_Element_Commit(element = %d)\n", element->handle));
1.1169 +
1.1170 + /* replace source/mask ONLY if it has changed. without these checks,
1.1171 + * both source and mask would be overwritten whenever one of them
1.1172 + * is changed.
1.1173 + */
1.1174 +
1.1175 + if (element->cachedSource != element->source)
1.1176 + {
1.1177 + element->source = element->cachedSource;
1.1178 + }
1.1179 +
1.1180 + if (element->cachedMask != element->mask)
1.1181 + {
1.1182 + element->mask = element->cachedMask;
1.1183 + }
1.1184 +
1.1185 + /* these must be reset now that the element is committed -- the only purpose
1.1186 + * of these cached ones is to have source/mask object pointers in the
1.1187 + * element so that source/mask can be safely deleted from the device even
1.1188 + * if that particular image provider is set as source/mask for some element
1.1189 + * that is not yet committed.
1.1190 + */
1.1191 +
1.1192 + DPRINT((" Prior to destroying cached objects:"));
1.1193 + DPRINT((" R(cachedMask) = %d", REFCOUNT(element->cachedMask)));
1.1194 + DPRINT((" R(cachedSource) = %d", REFCOUNT(element->cachedSource)));
1.1195 +
1.1196 + element->cachedSource = NULL;
1.1197 + element->cachedMask = NULL;
1.1198 +
1.1199 + DPRINT((" new source = %d\n", element->source ?
1.1200 + element->source->handle : 0));
1.1201 + DPRINT((" new mask = %d\n", element->mask ?
1.1202 + element->mask->handle : 0));
1.1203 +}
1.1204 +
1.1205 +
1.1206 +
1.1207 +#ifdef __cplusplus
1.1208 +}
1.1209 +#endif
1.1210 +