os/graphics/graphicscomposition/openwfcompositionengine/composition/src/wfcpipeline.c
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/graphicscomposition/openwfcompositionengine/composition/src/wfcpipeline.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,839 @@
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 +
1.27 +/*! \ingroup wfc
1.28 + * \file wfcpipeline.c
1.29 + *
1.30 + * \brief SI Composition pipeline stages
1.31 + *
1.32 + * Each pipeline stage is implemented in their respective functions
1.33 + * that take context and element as parameter. Composition status is
1.34 + * stored in elements state variable (struct WFC_ELEMENT_STATE.)
1.35 + * State has no strict input/output variables, each stage reads/writes
1.36 + * those variables it needs
1.37 + */
1.38 +#include <string.h>
1.39 +#include <stdlib.h>
1.40 +#include <math.h>
1.41 +
1.42 +#include "WF/wfc.h"
1.43 +#include "wfccontext.h"
1.44 +#include "wfcelement.h"
1.45 +#include "wfcimageprovider.h"
1.46 +#include "wfcstructs.h"
1.47 +#include "wfcscene.h"
1.48 +
1.49 +#include "owfobject.h"
1.50 +
1.51 +#include "owfnativestream.h"
1.52 +#include "owfmemory.h"
1.53 +#include "owfimage.h"
1.54 +#include "owfdebug.h"
1.55 +
1.56 +#define EXTRA_PIXEL_BOUNDARY 2
1.57 +
1.58 +/*!
1.59 + * \brief Check element destination visibility
1.60 + *
1.61 + * Check if element's destination rectangle is
1.62 + * inside context's visible limits.
1.63 + *
1.64 + * \param context Context
1.65 + * \param element Element
1.66 + *
1.67 + * \return Boolean value indicating whether element is visible or not
1.68 + */
1.69 +
1.70 +static WFCboolean
1.71 +WFC_Pipeline_ElementIsVisible(WFC_CONTEXT* context, WFC_ELEMENT* element)
1.72 +{
1.73 + OWF_RECTANGLE bounds, rect, drect;
1.74 +
1.75 + if ((context->rotation == WFC_ROTATION_90) || (context->rotation == WFC_ROTATION_270))
1.76 + {
1.77 + OWF_Rect_Set(&bounds, 0, 0, context->targetHeight, context->targetWidth);
1.78 + }
1.79 + else
1.80 + {
1.81 + OWF_Rect_Set(&bounds, 0, 0, context->targetWidth, context->targetHeight);
1.82 + }
1.83 +
1.84 + OWF_Rect_Set(&rect, element->dstRect[0], element->dstRect[1],
1.85 + element->dstRect[2], element->dstRect[3]);
1.86 +
1.87 + /* check destination rectangle against bounds - exit if not visible */
1.88 + if (!OWF_Rect_Clip(&drect, &rect, &bounds))
1.89 + {
1.90 + return WFC_FALSE;
1.91 + }
1.92 +
1.93 + return WFC_TRUE;
1.94 +}
1.95 +
1.96 +static void
1.97 +WFC_Pipeline_BlendInfo(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
1.98 +{
1.99 +
1.100 + OWF_ASSERT(state);
1.101 +
1.102 + /* setup blending parameters */
1.103 + state->blendInfo.destination.image = context->state.internalTargetImage;
1.104 + state->blendInfo.destination.rectangle = &state->dstRect;
1.105 + state->blendInfo.source.image = state->scaledSourceImage;
1.106 + state->blendInfo.source.rectangle = &state->scaledSrcRect;
1.107 + state->blendInfo.mask = state->originalMaskImage ? state->maskImage : NULL;
1.108 + state->blendInfo.globalAlpha = state->globalAlpha;
1.109 +
1.110 + DPRINT((" globalAplha = %f", state->globalAlpha));
1.111 + /* no need to check with OWF_ALPHA_MIN_VALUE as it is zero */
1.112 + OWF_ASSERT(state->blendInfo.globalAlpha <= OWF_ALPHA_MAX_VALUE);
1.113 +}
1.114 +
1.115 +/*! Transform the source rectangle to represent the floating point viewport
1.116 + as an offset in the final rotation stage image */
1.117 +static void
1.118 +WFC_Pipeline_TransformSource(WFC_ELEMENT_STATE* state)
1.119 +{
1.120 + OWFfloat width, height, totalWidth, totalHeight,
1.121 + leftMargin, rightMargin,
1.122 + topMargin, bottomMargin,
1.123 + temp;
1.124 + OWF_FLIP_DIRECTION flipping;
1.125 + WFCRotation rotation;
1.126 +
1.127 +
1.128 + OWF_ASSERT(state);
1.129 +
1.130 + width = state->sourceRect[2];
1.131 + totalWidth = state->sourceRect[0] + state->sourceRect[2];
1.132 +
1.133 + height = state->sourceRect[3];
1.134 + totalHeight = state->sourceRect[1] + state->sourceRect[3];
1.135 +
1.136 + /* X margins - includes 1 pixel border */
1.137 + leftMargin = (state->sourceRect[0] - ((float) floor(state->sourceRect[0]))) + 1.0f;
1.138 + rightMargin = (((float) ceil(totalWidth)) - totalWidth) + 1.0f;
1.139 +
1.140 + /* Y margins - includes 1 pixel border */
1.141 + topMargin = (state->sourceRect[1] - ((float) floor(state->sourceRect[1]))) + 1.0f;
1.142 + bottomMargin = (((float) ceil(totalHeight)) - totalHeight) + 1.0f;
1.143 +
1.144 + /* flip stages */
1.145 + flipping = state->sourceFlip > 0.0f ? OWF_FLIP_VERTICALLY
1.146 + : OWF_FLIP_NONE;
1.147 +
1.148 + /* top margin needs to be the bottom margin */
1.149 + if (flipping & OWF_FLIP_VERTICALLY)
1.150 + {
1.151 + temp = topMargin;
1.152 + topMargin = bottomMargin;
1.153 + bottomMargin = temp;
1.154 + }
1.155 +
1.156 + /* rotation stages */
1.157 + rotation = state->rotation;
1.158 +
1.159 + switch (rotation)
1.160 + {
1.161 + case WFC_ROTATION_0:
1.162 + {
1.163 + break;
1.164 + }
1.165 +
1.166 + case WFC_ROTATION_90:
1.167 + {
1.168 + /* switch width and height */
1.169 + temp = width;
1.170 + width = height;
1.171 + height = temp;
1.172 +
1.173 + topMargin = leftMargin;
1.174 + leftMargin = bottomMargin;
1.175 +
1.176 + break;
1.177 + }
1.178 +
1.179 + case WFC_ROTATION_180:
1.180 + {
1.181 + leftMargin = rightMargin;
1.182 + topMargin = bottomMargin;
1.183 +
1.184 + break;
1.185 + }
1.186 +
1.187 + case WFC_ROTATION_270:
1.188 + {
1.189 + /* switch width and height */
1.190 + temp = width;
1.191 + width = height;
1.192 + height = temp;
1.193 +
1.194 + leftMargin = topMargin;
1.195 + topMargin = rightMargin;
1.196 +
1.197 + break;
1.198 + }
1.199 +
1.200 + default:
1.201 + {
1.202 + OWF_ASSERT(0);
1.203 + }
1.204 + }
1.205 +
1.206 + /* X offset */
1.207 + state->transformedSourceRect[0] = leftMargin;
1.208 + /* Y offset */
1.209 + state->transformedSourceRect[1] = topMargin;
1.210 + /* width */
1.211 + state->transformedSourceRect[2] = width;
1.212 + /* height */
1.213 + state->transformedSourceRect[3] = height;
1.214 +}
1.215 +
1.216 +/*! Calculate the oversized integer crop region */
1.217 +static void
1.218 +WFC_Pipeline_OversizedViewport(WFC_ELEMENT_STATE* state)
1.219 +{
1.220 + OWFint width, height;
1.221 +
1.222 + state->oversizedCropRect.x = (int) floor(state->sourceRect[0]);
1.223 + state->oversizedCropRect.y = (int) floor(state->sourceRect[1]);
1.224 +
1.225 + width = (int) ceil(state->sourceRect[0] + state->sourceRect[2]);
1.226 + state->oversizedCropRect.width = (width - state->oversizedCropRect.x) + EXTRA_PIXEL_BOUNDARY;
1.227 +
1.228 + height = (int) ceil(state->sourceRect[1] + state->sourceRect[3]);
1.229 + state->oversizedCropRect.height = (height - state->oversizedCropRect.y) + EXTRA_PIXEL_BOUNDARY;
1.230 +}
1.231 +
1.232 +/*-----------------------------------------------------------*
1.233 + * Initial creation of element state object created just once per context
1.234 + *-----------------------------------------------------------*/
1.235 +OWF_API_CALL void WFC_Pipeline_DestroyState(WFC_CONTEXT* context)
1.236 +{
1.237 + WFC_ELEMENT_STATE* state;
1.238 + state= &context->prototypeElementState;
1.239 + OWF_Image_Destroy(state->scaledSourceImage);
1.240 + OWF_Image_Destroy(state->croppedSourceImage);
1.241 + OWF_Image_Destroy(state->convertedSourceImage);
1.242 + OWF_Image_Destroy(state->rotatedSourceIntermediateImage);
1.243 + OWF_Image_Destroy(state->flippedSourceImage);
1.244 + OWF_Image_Destroy(state->rotatedSourceImage);
1.245 + OWF_Image_Destroy(state->maskImage);
1.246 + state->scaledSourceImage=NULL;
1.247 + state->croppedSourceImage=NULL;
1.248 + state->convertedSourceImage=NULL;
1.249 + state->rotatedSourceIntermediateImage=NULL;
1.250 + state->flippedSourceImage=NULL;
1.251 + state->rotatedSourceImage=NULL;
1.252 + state->maskImage=NULL;
1.253 +}
1.254 +
1.255 +OWF_API_CALL OWFboolean WFC_Pipeline_CreateState(WFC_CONTEXT* context)
1.256 +{
1.257 + WFC_ELEMENT_STATE* state;
1.258 + OWF_IMAGE_FORMAT fmt;
1.259 +
1.260 + fmt.pixelFormat = OWF_IMAGE_ARGB_INTERNAL;
1.261 + fmt.linear = OWF_FALSE;
1.262 + fmt.premultiplied = OWF_FALSE;
1.263 + fmt.rowPadding = 1;
1.264 + state= &context->prototypeElementState;
1.265 + /* All buffers are initially created the full size of the scratch buffers, whicgh records the buffer size in bytes */
1.266 + state->convertedSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[1], 0);
1.267 + state->croppedSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[2], 0);
1.268 + state->flippedSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[2], 0);
1.269 +
1.270 + state->rotatedSourceIntermediateImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[1], 0);
1.271 + state->rotatedSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[2], 0);
1.272 + state->scaledSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[3], 0);
1.273 + fmt.pixelFormat = OWF_IMAGE_L32;
1.274 + state->maskImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[4], 0);
1.275 + if (!state->convertedSourceImage||!state->croppedSourceImage||!state->flippedSourceImage
1.276 + ||!state->rotatedSourceIntermediateImage||!state->rotatedSourceImage
1.277 + ||!state->scaledSourceImage||!state->maskImage
1.278 + )
1.279 + {
1.280 + WFC_Pipeline_DestroyState(context);
1.281 + return OWF_FALSE;
1.282 + }
1.283 + return OWF_TRUE;
1.284 +}
1.285 +
1.286 +
1.287 +/*---------------------------------------------------------------------------
1.288 + * Composition pipeline preparation
1.289 + *
1.290 + * \param context Context
1.291 + * \param element Element
1.292 + *
1.293 + * \return Boolean value indicating whether preparation succeeded
1.294 + *----------------------------------------------------------------------------*/
1.295 +#ifdef DEBUG
1.296 +/* reset size to original extent then try to set it to the target size */
1.297 +#define CREATE_WITH_LIMITS(img, imgW, imgH, fmt, maxW, maxH) \
1.298 + { \
1.299 + OWFboolean resized; \
1.300 + OWF_Image_SetSize(img, maxW, maxH); \
1.301 + OWF_Image_SetFlags(img,(fmt)->premultiplied,(fmt)->linear); \
1.302 + resized = OWF_Image_SetSize(img, imgW, imgH); \
1.303 + OWF_ASSERT(resized); \
1.304 + }
1.305 +#else
1.306 +#define CREATE_WITH_LIMITS(img, imgW, imgH, fmt, maxW, maxH) \
1.307 + { \
1.308 + OWF_Image_SetSize(img, maxW, maxH); \
1.309 + OWF_Image_SetFlags(img,(fmt)->premultiplied,(fmt)->linear); \
1.310 + OWF_Image_SetSize(img, imgW, imgH); \
1.311 + }
1.312 +#endif
1.313 +OWF_API_CALL WFC_ELEMENT_STATE*
1.314 +WFC_Pipeline_BeginComposition(WFC_CONTEXT* context, WFC_ELEMENT* element)
1.315 +{
1.316 + WFC_ELEMENT_STATE* state = &context->prototypeElementState;
1.317 + OWF_IMAGE_FORMAT imgf;
1.318 + OWFint sourceWidth;
1.319 + OWFint sourceHeight;
1.320 + OWFint x;
1.321 + OWFint tempWidth, tempHeight;
1.322 +
1.323 +
1.324 + DPRINT(("WFC_Element_BeginComposition(%x,%x)",
1.325 + context ? context->handle : 0, element ? element->handle : 0));
1.326 +
1.327 + if (!context || !element)
1.328 + {
1.329 + DPRINT((" context == NULL || element == NULL"));
1.330 + return NULL;
1.331 + }
1.332 +
1.333 + if (!WFC_Pipeline_ElementIsVisible(context, element))
1.334 + {
1.335 + DPRINT((" element [%x] totally outside of target - skipped",
1.336 + element ? element->handle : 0));
1.337 + return NULL;
1.338 + }
1.339 +
1.340 + /* setup temporary images used in composition. since the original
1.341 + source data must not be altered, we must copy it to scratch buffer
1.342 + and work it there. another scratch buffer is needed for scaling
1.343 + the image to its final size. same applies for masks; thus a grand total
1.344 + of 4 scratch buffers are needed. */
1.345 + OWF_ASSERT(element->source);
1.346 + OWF_ASSERT(element->source->streamHandle);
1.347 +
1.348 + state->originalSourceImage = element->source->lockedStream.image;
1.349 + state->rotation = element->sourceRotation;
1.350 + state->sourceFlip = element->sourceFlip;
1.351 + state->globalAlpha = element->globalAlpha;
1.352 + state->sourceScaleFilter = element->sourceScaleFilter;
1.353 + state->transparencyTypes = element->transparencyTypes;
1.354 +
1.355 + if (state->transparencyTypes & WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA)
1.356 + {
1.357 + if (state->globalAlpha == OWF_FULLY_TRANSPARENT)
1.358 + {
1.359 + /* Fully transparent element - no contribution. */
1.360 + return NULL;
1.361 + }
1.362 + if (state->globalAlpha == OWF_FULLY_OPAQUE)
1.363 + {
1.364 + /* Fully opaque global alpha - global alpha can be ignored */
1.365 + state->transparencyTypes &= ~WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA;
1.366 + }
1.367 + }
1.368 +
1.369 +/* replicate the source viewport rectangle and target extent rectangle */
1.370 + for (x = 0; x < 4; x++)
1.371 + {
1.372 + state->sourceRect[x] = element->srcRect[x];
1.373 + state->destinationRect[x] = element->dstRect[x];
1.374 + }
1.375 + OWF_Rect_Set(&state->dstRect, element->dstRect[0], element->dstRect[1],
1.376 + element->dstRect[2], element->dstRect[3]);
1.377 +
1.378 + /* transform the source rectangle to represent the floating point viewport
1.379 + as an offset in the final rotation stage image */
1.380 + WFC_Pipeline_TransformSource(state);
1.381 +
1.382 + imgf.pixelFormat = OWF_IMAGE_ARGB_INTERNAL;
1.383 + imgf.linear = element->source->lockedStream.image->format.linear;
1.384 + imgf.premultiplied = element->source->lockedStream.image->format.premultiplied;
1.385 + imgf.rowPadding = 1;
1.386 +
1.387 + /* add a 1 pixel boundary so we can replicate the edges */
1.388 + sourceWidth = element->source->lockedStream.image->width + EXTRA_PIXEL_BOUNDARY;
1.389 + sourceHeight = element->source->lockedStream.image->height + EXTRA_PIXEL_BOUNDARY;
1.390 +
1.391 + CREATE_WITH_LIMITS(state->convertedSourceImage,
1.392 + sourceWidth,
1.393 + sourceHeight,
1.394 + &imgf,
1.395 + MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
1.396 +
1.397 + /* calculate the oversized integer crop region (inc. 1 pixel boundary)
1.398 + so edge replication can be performed */
1.399 + WFC_Pipeline_OversizedViewport(state);
1.400 +
1.401 + /* subsequent temporary renderstage pipeline images need to use the oversized
1.402 + integer crop region */
1.403 + CREATE_WITH_LIMITS(state->croppedSourceImage,
1.404 + state->oversizedCropRect.width, state->oversizedCropRect.height,
1.405 + &imgf,
1.406 + MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
1.407 +
1.408 + CREATE_WITH_LIMITS(state->flippedSourceImage,
1.409 + state->oversizedCropRect.width, state->oversizedCropRect.height,
1.410 + &imgf,
1.411 + MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
1.412 +
1.413 +
1.414 + if (state->rotation == WFC_ROTATION_90 || state->rotation == WFC_ROTATION_270)
1.415 + {
1.416 + tempHeight = state->oversizedCropRect.width;
1.417 + tempWidth = state->oversizedCropRect.height;
1.418 + }
1.419 + else
1.420 + {
1.421 + tempWidth = state->oversizedCropRect.width;
1.422 + tempHeight = state->oversizedCropRect.height;
1.423 + }
1.424 +
1.425 + CREATE_WITH_LIMITS(state->rotatedSourceIntermediateImage,
1.426 + tempWidth, tempHeight,
1.427 + &imgf,
1.428 + MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
1.429 +
1.430 +
1.431 + /* no rotation required - just use the previous stages (flip) buffer */
1.432 + CREATE_WITH_LIMITS(state->rotatedSourceImage,
1.433 + tempWidth, tempHeight,
1.434 + &imgf,
1.435 + MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
1.436 +
1.437 + /* finally, scaled image uses destination width and height */
1.438 + OWF_Rect_Set(&state->scaledSrcRect, 0, 0, element->dstRect[2], element->dstRect[3]);
1.439 + CREATE_WITH_LIMITS(state->scaledSourceImage,
1.440 + state->scaledSrcRect.width,
1.441 + state->scaledSrcRect.height,
1.442 + &imgf,
1.443 + MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
1.444 +
1.445 + if (!(state->convertedSourceImage && state->croppedSourceImage &&
1.446 + state->scaledSourceImage && state->rotatedSourceIntermediateImage &&
1.447 + state->flippedSourceImage && state->rotatedSourceImage))
1.448 + {
1.449 + DPRINT((" Preparation of intermediate pipeline image buffers failed"
1.450 + " (May be caused by overflow or out-of-memory situation)"));
1.451 + DPRINT((" convertedSourceImage = %p", state->convertedSourceImage));
1.452 + DPRINT((" croppedSourceImage = %p", state->croppedSourceImage));
1.453 + DPRINT((" scaledSourceImage = %p", state->scaledSourceImage));
1.454 + DPRINT((" rotatedSourceIntermediateImage = %p", state->rotatedSourceIntermediateImage));
1.455 + DPRINT((" flippedSourceImage = %p", state->flippedSourceImage));
1.456 + DPRINT((" rotatedSourceImage = %p", state->rotatedSourceImage));
1.457 +
1.458 +
1.459 + return (WFC_ELEMENT_STATE*)WFC_FALSE;
1.460 + }
1.461 +
1.462 +#ifdef DEBUG
1.463 + OWF_Image_Clear(state->convertedSourceImage, 0, 0, 0, 0);
1.464 + OWF_Image_Clear(state->croppedSourceImage, 0, 0, 0, 0);
1.465 + OWF_Image_Clear(state->scaledSourceImage, 0, 0, 0, 0);
1.466 + OWF_Image_Clear(state->rotatedSourceIntermediateImage, 0, 0, 0, 0);
1.467 + OWF_Image_Clear(state->flippedSourceImage, 0, 0, 0, 0);
1.468 + OWF_Image_Clear(state->rotatedSourceImage, 0, 0, 0, 0);
1.469 +#endif
1.470 +
1.471 + /* setup mask in case the element has one */
1.472 + if (element->maskComposed)
1.473 + {
1.474 + OWF_IMAGE* image = NULL;
1.475 + OWFsubpixel* pix = NULL;
1.476 + WFCint i = 0;
1.477 +
1.478 + DPRINT(("Processing element mask"));
1.479 + OWF_ASSERT(&element->mask);
1.480 + OWF_ASSERT(&element->mask->streamHandle);
1.481 + image = element->mask->lockedStream.image;
1.482 + OWF_ASSERT(image);
1.483 +
1.484 + state->originalMaskImage = element->mask->lockedStream.image;
1.485 +
1.486 + imgf.pixelFormat = OWF_IMAGE_L32;
1.487 + imgf.linear = image->format.linear;
1.488 + imgf.premultiplied = image->format.premultiplied;
1.489 +
1.490 + /* mask size is always same as destination rect's */
1.491 + DPRINT(("Binding stream image to scratch buffer"));
1.492 + CREATE_WITH_LIMITS(state->maskImage,
1.493 + state->scaledSrcRect.width,
1.494 + state->scaledSrcRect.height,
1.495 + &imgf,
1.496 + MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
1.497 +
1.498 + /* initialize mask */
1.499 + DPRINT(("Initializing mask, size = %dx%d", state->scaledSrcRect.width,
1.500 + state->scaledSrcRect.height));
1.501 + pix = (OWFsubpixel*) state->maskImage->data;
1.502 + for (i = 0; i < state->scaledSrcRect.width * state->scaledSrcRect.height; i++)
1.503 + {
1.504 + pix[i] = OWF_FULLY_OPAQUE;
1.505 + }
1.506 + }
1.507 + else
1.508 + {
1.509 + state->originalMaskImage=NULL;
1.510 + }
1.511 +
1.512 + WFC_Pipeline_BlendInfo(context, state);
1.513 +
1.514 + DPRINT((" Cropped source image size is %dx%d",
1.515 + state->croppedSourceImage->width, state->croppedSourceImage->height));
1.516 + DPRINT((" Scaled source image size is %dx%d",
1.517 + state->scaledSourceImage->width, state->scaledSourceImage->height));
1.518 + DPRINT((" Mirrored source intermediate image size is %dx%d",
1.519 + state->rotatedSourceIntermediateImage->width, state->rotatedSourceIntermediateImage->height));
1.520 + DPRINT((" Mirrored source image size is %dx%d",
1.521 + state->flippedSourceImage->width, state->flippedSourceImage->height));
1.522 + DPRINT((" Rotated source image size is %dx%d",
1.523 + state->rotatedSourceImage->width, state->rotatedSourceImage->height));
1.524 +
1.525 + return state;
1.526 +}
1.527 +
1.528 +/*---------------------------------------------------------------------------
1.529 + * Composition pipeline cleanup
1.530 + *
1.531 + * \param context Context
1.532 + * \param element Element
1.533 + *----------------------------------------------------------------------------*/
1.534 +OWF_API_CALL void
1.535 +WFC_Pipeline_EndComposition(WFC_CONTEXT* context, WFC_ELEMENT* element, WFC_ELEMENT_STATE* state)
1.536 +{
1.537 +
1.538 + if (!context || !element)
1.539 + {
1.540 + DPRINT(("WFC_Element_EndComposition: context == NULL || "
1.541 + "element == NULL"));
1.542 + }
1.543 +
1.544 +
1.545 + OWF_ASSERT(state);
1.546 + state->originalSourceImage=NULL;
1.547 + state->originalMaskImage=NULL;
1.548 +
1.549 +}
1.550 +
1.551 +/*---------------------------------------------------------------------------
1.552 + * \brief Source conversion stage
1.553 + *
1.554 + * \param context Context
1.555 + * \param element Element
1.556 + *----------------------------------------------------------------------------*/
1.557 +OWF_API_CALL void
1.558 +WFC_Pipeline_ExecuteSourceConversionStage(WFC_CONTEXT* context,
1.559 + WFC_ELEMENT_STATE* state)
1.560 +{
1.561 + /* this stage could be embedded in cropping stage */
1.562 +
1.563 +
1.564 + if (NULL == context || NULL == state)
1.565 + {
1.566 + DPRINT(("WFC_Context_ExecuteSourceConversionStage: context = %p, "
1.567 + "state = %p",
1.568 + context, state));
1.569 + return;
1.570 + }
1.571 +
1.572 + OWF_ASSERT(state->originalSourceImage);
1.573 +
1.574 + OWF_Image_SourceFormatConversion(state->convertedSourceImage,
1.575 + state->originalSourceImage);
1.576 +
1.577 + /* convert mask from stream format to internal format */
1.578 + if (state->originalMaskImage)
1.579 + {
1.580 + if (!OWF_Image_ConvertMask(state->maskImage, state->originalMaskImage))
1.581 + {
1.582 + state->originalMaskImage=NULL;
1.583 + }
1.584 + }
1.585 +}
1.586 +
1.587 +/*---------------------------------------------------------------------------
1.588 + * \brief Crop stage
1.589 + *
1.590 + * \param context Context
1.591 + * \param element Element
1.592 + *----------------------------------------------------------------------------*/
1.593 +OWF_API_CALL void
1.594 +WFC_Pipeline_ExecuteCropStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
1.595 +{
1.596 + OWF_RECTANGLE sourceRect,
1.597 + cropRect;
1.598 +
1.599 + DPRINT(("WFC_Pipeline_ExecuteCropStage"));
1.600 +
1.601 + if (NULL == context || NULL == state)
1.602 + {
1.603 + DPRINT(("WFC_Context_ExecuteCropStage: context = %p, state = %p",
1.604 + context, state));
1.605 + }
1.606 + else
1.607 + {
1.608 + /* Source rectangle */
1.609 + OWF_Rect_Set(&sourceRect,
1.610 + state->oversizedCropRect.x, state->oversizedCropRect.y,
1.611 + state->oversizedCropRect.width, state->oversizedCropRect.height);
1.612 +
1.613 + /* cropped source size - supports oversized integer and 1 pixel boundary */
1.614 + OWF_Rect_Set(&cropRect,
1.615 + 0, 0,
1.616 + state->oversizedCropRect.width, state->oversizedCropRect.height);
1.617 +
1.618 + OWF_Image_Blit(state->croppedSourceImage, &cropRect,
1.619 + state->convertedSourceImage, &sourceRect);
1.620 + }
1.621 +}
1.622 +
1.623 +/*---------------------------------------------------------------------------
1.624 + * \brief Flip stage
1.625 + *
1.626 + * \param context Context
1.627 + * \param element Element
1.628 + *----------------------------------------------------------------------------*/
1.629 +OWF_API_CALL void
1.630 +WFC_Pipeline_ExecuteFlipStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
1.631 +{
1.632 + OWF_FLIP_DIRECTION flipping;
1.633 +
1.634 + if (NULL == context || NULL == state)
1.635 + {
1.636 + DPRINT(("WFC_Context_ExecuteFlipStage: context = %p, state = %p",
1.637 + context, state));
1.638 + }
1.639 + else
1.640 + {
1.641 + flipping = state->sourceFlip > 0.0f ? OWF_FLIP_VERTICALLY
1.642 + : OWF_FLIP_NONE;
1.643 +
1.644 + OWF_Image_Flip(state->flippedSourceImage, flipping);
1.645 + }
1.646 +}
1.647 +
1.648 +/*---------------------------------------------------------------------------
1.649 + * \brief Rotation stage
1.650 + *
1.651 + * \param context Context
1.652 + * \param element Element
1.653 + *----------------------------------------------------------------------------*/
1.654 +OWF_API_CALL void
1.655 +WFC_Pipeline_ExecuteRotationStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
1.656 +{
1.657 + OWF_ROTATION rot = OWF_ROTATION_0;
1.658 + OWF_RECTANGLE rect;
1.659 + WFCRotation rotation;
1.660 +
1.661 + if (NULL == context || NULL == state)
1.662 + {
1.663 + DPRINT(("WFC_Context_ExecuteRotationStage: context = %p, state = %p",
1.664 + context, state));
1.665 + return;
1.666 + }
1.667 +
1.668 + rotation = state->rotation;
1.669 + DPRINT((" Element rotation = %d", rotation));
1.670 +
1.671 + switch (rotation)
1.672 + {
1.673 + case WFC_ROTATION_0:
1.674 + {
1.675 + return; /* Rotate copies back into input buffer so just skip */
1.676 + }
1.677 +
1.678 + case WFC_ROTATION_90:
1.679 + {
1.680 + rot = OWF_ROTATION_90;
1.681 + break;
1.682 + }
1.683 +
1.684 + case WFC_ROTATION_180:
1.685 + {
1.686 + rot = OWF_ROTATION_180;
1.687 + break;
1.688 + }
1.689 +
1.690 + case WFC_ROTATION_270:
1.691 + {
1.692 + rot = OWF_ROTATION_270;
1.693 + break;
1.694 + }
1.695 +
1.696 + default:
1.697 + {
1.698 + OWF_ASSERT(0);
1.699 + }
1.700 + }
1.701 +
1.702 + /* rotate the the image using rotatedSourceIntermediateImage */
1.703 + OWF_Image_Rotate(state->rotatedSourceIntermediateImage,
1.704 + state->flippedSourceImage,
1.705 + rot);
1.706 +
1.707 + /* blit rotated image back to original image buffer */
1.708 + rect.x = 0;
1.709 + rect.y = 0;
1.710 + rect.width = state->rotatedSourceIntermediateImage->width;
1.711 + rect.height = state->rotatedSourceIntermediateImage->height;
1.712 +
1.713 + DPRINT((" Source image dimensions after rotation = %dx%d",
1.714 + rect.width, rect.height));
1.715 +
1.716 + OWF_Image_Blit(state->rotatedSourceImage,
1.717 + &rect,
1.718 + state->rotatedSourceIntermediateImage,
1.719 + &rect);
1.720 +
1.721 +}
1.722 +
1.723 +/*---------------------------------------------------------------------------
1.724 + * \brief Scaling stage
1.725 + *
1.726 + * \param context Context
1.727 + * \param element Element
1.728 + *----------------------------------------------------------------------------*/
1.729 +OWF_API_CALL void
1.730 +WFC_Pipeline_ExecuteScalingStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
1.731 +{
1.732 + OWF_RECTANGLE scaledRect,
1.733 + cropRect;
1.734 + OWF_FILTERING filteringMode = OWF_FILTER_POINT_SAMPLING;
1.735 + WFCScaleFilter filter;
1.736 +
1.737 + DPRINT(("WFC_Context_ExecuteScalingStage(%p,%p)", context, state));
1.738 +
1.739 + if (NULL == context || NULL == state)
1.740 + {
1.741 + DPRINT(("WFC_Context_ExecuteScalingStage: context = %p, state = %p",
1.742 + context, state));
1.743 + return;
1.744 + }
1.745 +
1.746 + filter = state->sourceScaleFilter;
1.747 +
1.748 + switch (filter)
1.749 + {
1.750 + case WFC_SCALE_FILTER_NONE:
1.751 + case WFC_SCALE_FILTER_FASTER:
1.752 + {
1.753 + filteringMode = OWF_FILTER_POINT_SAMPLING;
1.754 + DPRINT((" Using point-sampling filter"));
1.755 + break;
1.756 + }
1.757 + case WFC_SCALE_FILTER_BETTER:
1.758 + {
1.759 + filteringMode = OWF_FILTER_BILINEAR;
1.760 + DPRINT((" Using bilinear filter"));
1.761 + break;
1.762 + }
1.763 +
1.764 + case WFC_SCALE_FILTER_FORCE_32BIT:
1.765 + {
1.766 + /* To shut the compiler up -- not a valid filtering mode.
1.767 + * Validity is ensured when the filter attribute value
1.768 + * is set, thus it shouldn't have this value ever. */
1.769 + OWF_ASSERT(0);
1.770 + break;
1.771 + }
1.772 + }
1.773 +
1.774 + OWF_Rect_Set(&cropRect, 1, 1,
1.775 + state->rotatedSourceImage->width - EXTRA_PIXEL_BOUNDARY,
1.776 + state->rotatedSourceImage->height - EXTRA_PIXEL_BOUNDARY);
1.777 +
1.778 + OWF_Rect_Set(&scaledRect, 0, 0, state->destinationRect[2], state->destinationRect[3]);
1.779 +
1.780 + if ( scaledRect.width != state->transformedSourceRect[2]
1.781 + || scaledRect.height != state->transformedSourceRect[3]
1.782 + || state->sourceRect[0] != floor(state->sourceRect[0])
1.783 + || state->sourceRect[1] != floor(state->sourceRect[1])
1.784 + )
1.785 + {
1.786 + /* scale the image */
1.787 + OWF_Image_Stretch(state->scaledSourceImage, &scaledRect,
1.788 + state->rotatedSourceImage, state->transformedSourceRect,
1.789 + filteringMode);
1.790 + }
1.791 + else
1.792 + {
1.793 + /* 1:1 copy, no need to scale */
1.794 + OWF_Image_Blit(state->scaledSourceImage, &scaledRect,
1.795 + state->rotatedSourceImage, &cropRect);
1.796 + }
1.797 +
1.798 +}
1.799 +
1.800 +/*---------------------------------------------------------------------------
1.801 + * \brief Blending stage
1.802 + *
1.803 + * \param context Context
1.804 + * \param element Element
1.805 + *----------------------------------------------------------------------------*/
1.806 +OWF_API_CALL void
1.807 +WFC_Pipeline_ExecuteBlendingStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
1.808 +{
1.809 + OWF_TRANSPARENCY blendMode = OWF_TRANSPARENCY_NONE;
1.810 + WFCbitfield transparency = 0;
1.811 +
1.812 + DPRINT(("WFC_Pipeline_ExecuteBlendingStage"));
1.813 +
1.814 + if (NULL == context || NULL == state)
1.815 + {
1.816 + return;
1.817 + }
1.818 +
1.819 + DPRINT((" context = %d, state = %d",
1.820 + context->handle, state));
1.821 +
1.822 + transparency = state->transparencyTypes;
1.823 + blendMode = OWF_TRANSPARENCY_NONE;
1.824 +
1.825 + if (transparency & WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA)
1.826 + {
1.827 + blendMode = (OWF_TRANSPARENCY)(blendMode|OWF_TRANSPARENCY_GLOBAL_ALPHA);
1.828 + }
1.829 +
1.830 + if (transparency & WFC_TRANSPARENCY_SOURCE)
1.831 + {
1.832 + OWF_Image_PremultiplyAlpha(state->scaledSourceImage);
1.833 + blendMode = (OWF_TRANSPARENCY)(blendMode|OWF_TRANSPARENCY_SOURCE_ALPHA);
1.834 + }
1.835 +
1.836 + if ((transparency & WFC_TRANSPARENCY_MASK) && state->originalMaskImage)
1.837 + {
1.838 + blendMode = (OWF_TRANSPARENCY)(blendMode|OWF_TRANSPARENCY_MASK);
1.839 + }
1.840 +
1.841 + OWF_Image_Blend(&state->blendInfo, blendMode);
1.842 +}