os/graphics/graphicscomposition/openwfcompositionengine/composition/src/wfcpipeline.c
First public contribution.
1 /* Copyright (c) 2009-2010 The Khronos Group Inc.
2 * Portions copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies)
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and/or associated documentation files (the
6 * "Materials"), to deal in the Materials without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Materials, and to
9 * permit persons to whom the Materials are furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Materials.
15 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
27 * \brief SI Composition pipeline stages
29 * Each pipeline stage is implemented in their respective functions
30 * that take context and element as parameter. Composition status is
31 * stored in elements state variable (struct WFC_ELEMENT_STATE.)
32 * State has no strict input/output variables, each stage reads/writes
33 * those variables it needs
40 #include "wfccontext.h"
41 #include "wfcelement.h"
42 #include "wfcimageprovider.h"
43 #include "wfcstructs.h"
46 #include "owfobject.h"
48 #include "owfnativestream.h"
49 #include "owfmemory.h"
53 #define EXTRA_PIXEL_BOUNDARY 2
56 * \brief Check element destination visibility
58 * Check if element's destination rectangle is
59 * inside context's visible limits.
61 * \param context Context
62 * \param element Element
64 * \return Boolean value indicating whether element is visible or not
68 WFC_Pipeline_ElementIsVisible(WFC_CONTEXT* context, WFC_ELEMENT* element)
70 OWF_RECTANGLE bounds, rect, drect;
72 if ((context->rotation == WFC_ROTATION_90) || (context->rotation == WFC_ROTATION_270))
74 OWF_Rect_Set(&bounds, 0, 0, context->targetHeight, context->targetWidth);
78 OWF_Rect_Set(&bounds, 0, 0, context->targetWidth, context->targetHeight);
81 OWF_Rect_Set(&rect, element->dstRect[0], element->dstRect[1],
82 element->dstRect[2], element->dstRect[3]);
84 /* check destination rectangle against bounds - exit if not visible */
85 if (!OWF_Rect_Clip(&drect, &rect, &bounds))
94 WFC_Pipeline_BlendInfo(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
99 /* setup blending parameters */
100 state->blendInfo.destination.image = context->state.internalTargetImage;
101 state->blendInfo.destination.rectangle = &state->dstRect;
102 state->blendInfo.source.image = state->scaledSourceImage;
103 state->blendInfo.source.rectangle = &state->scaledSrcRect;
104 state->blendInfo.mask = state->originalMaskImage ? state->maskImage : NULL;
105 state->blendInfo.globalAlpha = state->globalAlpha;
107 DPRINT((" globalAplha = %f", state->globalAlpha));
108 /* no need to check with OWF_ALPHA_MIN_VALUE as it is zero */
109 OWF_ASSERT(state->blendInfo.globalAlpha <= OWF_ALPHA_MAX_VALUE);
112 /*! Transform the source rectangle to represent the floating point viewport
113 as an offset in the final rotation stage image */
115 WFC_Pipeline_TransformSource(WFC_ELEMENT_STATE* state)
117 OWFfloat width, height, totalWidth, totalHeight,
118 leftMargin, rightMargin,
119 topMargin, bottomMargin,
121 OWF_FLIP_DIRECTION flipping;
122 WFCRotation rotation;
127 width = state->sourceRect[2];
128 totalWidth = state->sourceRect[0] + state->sourceRect[2];
130 height = state->sourceRect[3];
131 totalHeight = state->sourceRect[1] + state->sourceRect[3];
133 /* X margins - includes 1 pixel border */
134 leftMargin = (state->sourceRect[0] - ((float) floor(state->sourceRect[0]))) + 1.0f;
135 rightMargin = (((float) ceil(totalWidth)) - totalWidth) + 1.0f;
137 /* Y margins - includes 1 pixel border */
138 topMargin = (state->sourceRect[1] - ((float) floor(state->sourceRect[1]))) + 1.0f;
139 bottomMargin = (((float) ceil(totalHeight)) - totalHeight) + 1.0f;
142 flipping = state->sourceFlip > 0.0f ? OWF_FLIP_VERTICALLY
145 /* top margin needs to be the bottom margin */
146 if (flipping & OWF_FLIP_VERTICALLY)
149 topMargin = bottomMargin;
153 /* rotation stages */
154 rotation = state->rotation;
163 case WFC_ROTATION_90:
165 /* switch width and height */
170 topMargin = leftMargin;
171 leftMargin = bottomMargin;
176 case WFC_ROTATION_180:
178 leftMargin = rightMargin;
179 topMargin = bottomMargin;
184 case WFC_ROTATION_270:
186 /* switch width and height */
191 leftMargin = topMargin;
192 topMargin = rightMargin;
204 state->transformedSourceRect[0] = leftMargin;
206 state->transformedSourceRect[1] = topMargin;
208 state->transformedSourceRect[2] = width;
210 state->transformedSourceRect[3] = height;
213 /*! Calculate the oversized integer crop region */
215 WFC_Pipeline_OversizedViewport(WFC_ELEMENT_STATE* state)
217 OWFint width, height;
219 state->oversizedCropRect.x = (int) floor(state->sourceRect[0]);
220 state->oversizedCropRect.y = (int) floor(state->sourceRect[1]);
222 width = (int) ceil(state->sourceRect[0] + state->sourceRect[2]);
223 state->oversizedCropRect.width = (width - state->oversizedCropRect.x) + EXTRA_PIXEL_BOUNDARY;
225 height = (int) ceil(state->sourceRect[1] + state->sourceRect[3]);
226 state->oversizedCropRect.height = (height - state->oversizedCropRect.y) + EXTRA_PIXEL_BOUNDARY;
229 /*-----------------------------------------------------------*
230 * Initial creation of element state object created just once per context
231 *-----------------------------------------------------------*/
232 OWF_API_CALL void WFC_Pipeline_DestroyState(WFC_CONTEXT* context)
234 WFC_ELEMENT_STATE* state;
235 state= &context->prototypeElementState;
236 OWF_Image_Destroy(state->scaledSourceImage);
237 OWF_Image_Destroy(state->croppedSourceImage);
238 OWF_Image_Destroy(state->convertedSourceImage);
239 OWF_Image_Destroy(state->rotatedSourceIntermediateImage);
240 OWF_Image_Destroy(state->flippedSourceImage);
241 OWF_Image_Destroy(state->rotatedSourceImage);
242 OWF_Image_Destroy(state->maskImage);
243 state->scaledSourceImage=NULL;
244 state->croppedSourceImage=NULL;
245 state->convertedSourceImage=NULL;
246 state->rotatedSourceIntermediateImage=NULL;
247 state->flippedSourceImage=NULL;
248 state->rotatedSourceImage=NULL;
249 state->maskImage=NULL;
252 OWF_API_CALL OWFboolean WFC_Pipeline_CreateState(WFC_CONTEXT* context)
254 WFC_ELEMENT_STATE* state;
255 OWF_IMAGE_FORMAT fmt;
257 fmt.pixelFormat = OWF_IMAGE_ARGB_INTERNAL;
258 fmt.linear = OWF_FALSE;
259 fmt.premultiplied = OWF_FALSE;
261 state= &context->prototypeElementState;
262 /* All buffers are initially created the full size of the scratch buffers, whicgh records the buffer size in bytes */
263 state->convertedSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[1], 0);
264 state->croppedSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[2], 0);
265 state->flippedSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[2], 0);
267 state->rotatedSourceIntermediateImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[1], 0);
268 state->rotatedSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[2], 0);
269 state->scaledSourceImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[3], 0);
270 fmt.pixelFormat = OWF_IMAGE_L32;
271 state->maskImage=OWF_Image_Create(MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT, &fmt, context->scratchBuffer[4], 0);
272 if (!state->convertedSourceImage||!state->croppedSourceImage||!state->flippedSourceImage
273 ||!state->rotatedSourceIntermediateImage||!state->rotatedSourceImage
274 ||!state->scaledSourceImage||!state->maskImage
277 WFC_Pipeline_DestroyState(context);
284 /*---------------------------------------------------------------------------
285 * Composition pipeline preparation
287 * \param context Context
288 * \param element Element
290 * \return Boolean value indicating whether preparation succeeded
291 *----------------------------------------------------------------------------*/
293 /* reset size to original extent then try to set it to the target size */
294 #define CREATE_WITH_LIMITS(img, imgW, imgH, fmt, maxW, maxH) \
296 OWFboolean resized; \
297 OWF_Image_SetSize(img, maxW, maxH); \
298 OWF_Image_SetFlags(img,(fmt)->premultiplied,(fmt)->linear); \
299 resized = OWF_Image_SetSize(img, imgW, imgH); \
300 OWF_ASSERT(resized); \
303 #define CREATE_WITH_LIMITS(img, imgW, imgH, fmt, maxW, maxH) \
305 OWF_Image_SetSize(img, maxW, maxH); \
306 OWF_Image_SetFlags(img,(fmt)->premultiplied,(fmt)->linear); \
307 OWF_Image_SetSize(img, imgW, imgH); \
310 OWF_API_CALL WFC_ELEMENT_STATE*
311 WFC_Pipeline_BeginComposition(WFC_CONTEXT* context, WFC_ELEMENT* element)
313 WFC_ELEMENT_STATE* state = &context->prototypeElementState;
314 OWF_IMAGE_FORMAT imgf;
318 OWFint tempWidth, tempHeight;
321 DPRINT(("WFC_Element_BeginComposition(%x,%x)",
322 context ? context->handle : 0, element ? element->handle : 0));
324 if (!context || !element)
326 DPRINT((" context == NULL || element == NULL"));
330 if (!WFC_Pipeline_ElementIsVisible(context, element))
332 DPRINT((" element [%x] totally outside of target - skipped",
333 element ? element->handle : 0));
337 /* setup temporary images used in composition. since the original
338 source data must not be altered, we must copy it to scratch buffer
339 and work it there. another scratch buffer is needed for scaling
340 the image to its final size. same applies for masks; thus a grand total
341 of 4 scratch buffers are needed. */
342 OWF_ASSERT(element->source);
343 OWF_ASSERT(element->source->streamHandle);
345 state->originalSourceImage = element->source->lockedStream.image;
346 state->rotation = element->sourceRotation;
347 state->sourceFlip = element->sourceFlip;
348 state->globalAlpha = element->globalAlpha;
349 state->sourceScaleFilter = element->sourceScaleFilter;
350 state->transparencyTypes = element->transparencyTypes;
352 if (state->transparencyTypes & WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA)
354 if (state->globalAlpha == OWF_FULLY_TRANSPARENT)
356 /* Fully transparent element - no contribution. */
359 if (state->globalAlpha == OWF_FULLY_OPAQUE)
361 /* Fully opaque global alpha - global alpha can be ignored */
362 state->transparencyTypes &= ~WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA;
366 /* replicate the source viewport rectangle and target extent rectangle */
367 for (x = 0; x < 4; x++)
369 state->sourceRect[x] = element->srcRect[x];
370 state->destinationRect[x] = element->dstRect[x];
372 OWF_Rect_Set(&state->dstRect, element->dstRect[0], element->dstRect[1],
373 element->dstRect[2], element->dstRect[3]);
375 /* transform the source rectangle to represent the floating point viewport
376 as an offset in the final rotation stage image */
377 WFC_Pipeline_TransformSource(state);
379 imgf.pixelFormat = OWF_IMAGE_ARGB_INTERNAL;
380 imgf.linear = element->source->lockedStream.image->format.linear;
381 imgf.premultiplied = element->source->lockedStream.image->format.premultiplied;
384 /* add a 1 pixel boundary so we can replicate the edges */
385 sourceWidth = element->source->lockedStream.image->width + EXTRA_PIXEL_BOUNDARY;
386 sourceHeight = element->source->lockedStream.image->height + EXTRA_PIXEL_BOUNDARY;
388 CREATE_WITH_LIMITS(state->convertedSourceImage,
392 MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
394 /* calculate the oversized integer crop region (inc. 1 pixel boundary)
395 so edge replication can be performed */
396 WFC_Pipeline_OversizedViewport(state);
398 /* subsequent temporary renderstage pipeline images need to use the oversized
399 integer crop region */
400 CREATE_WITH_LIMITS(state->croppedSourceImage,
401 state->oversizedCropRect.width, state->oversizedCropRect.height,
403 MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
405 CREATE_WITH_LIMITS(state->flippedSourceImage,
406 state->oversizedCropRect.width, state->oversizedCropRect.height,
408 MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
411 if (state->rotation == WFC_ROTATION_90 || state->rotation == WFC_ROTATION_270)
413 tempHeight = state->oversizedCropRect.width;
414 tempWidth = state->oversizedCropRect.height;
418 tempWidth = state->oversizedCropRect.width;
419 tempHeight = state->oversizedCropRect.height;
422 CREATE_WITH_LIMITS(state->rotatedSourceIntermediateImage,
423 tempWidth, tempHeight,
425 MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
428 /* no rotation required - just use the previous stages (flip) buffer */
429 CREATE_WITH_LIMITS(state->rotatedSourceImage,
430 tempWidth, tempHeight,
432 MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
434 /* finally, scaled image uses destination width and height */
435 OWF_Rect_Set(&state->scaledSrcRect, 0, 0, element->dstRect[2], element->dstRect[3]);
436 CREATE_WITH_LIMITS(state->scaledSourceImage,
437 state->scaledSrcRect.width,
438 state->scaledSrcRect.height,
440 MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
442 if (!(state->convertedSourceImage && state->croppedSourceImage &&
443 state->scaledSourceImage && state->rotatedSourceIntermediateImage &&
444 state->flippedSourceImage && state->rotatedSourceImage))
446 DPRINT((" Preparation of intermediate pipeline image buffers failed"
447 " (May be caused by overflow or out-of-memory situation)"));
448 DPRINT((" convertedSourceImage = %p", state->convertedSourceImage));
449 DPRINT((" croppedSourceImage = %p", state->croppedSourceImage));
450 DPRINT((" scaledSourceImage = %p", state->scaledSourceImage));
451 DPRINT((" rotatedSourceIntermediateImage = %p", state->rotatedSourceIntermediateImage));
452 DPRINT((" flippedSourceImage = %p", state->flippedSourceImage));
453 DPRINT((" rotatedSourceImage = %p", state->rotatedSourceImage));
456 return (WFC_ELEMENT_STATE*)WFC_FALSE;
460 OWF_Image_Clear(state->convertedSourceImage, 0, 0, 0, 0);
461 OWF_Image_Clear(state->croppedSourceImage, 0, 0, 0, 0);
462 OWF_Image_Clear(state->scaledSourceImage, 0, 0, 0, 0);
463 OWF_Image_Clear(state->rotatedSourceIntermediateImage, 0, 0, 0, 0);
464 OWF_Image_Clear(state->flippedSourceImage, 0, 0, 0, 0);
465 OWF_Image_Clear(state->rotatedSourceImage, 0, 0, 0, 0);
468 /* setup mask in case the element has one */
469 if (element->maskComposed)
471 OWF_IMAGE* image = NULL;
472 OWFsubpixel* pix = NULL;
475 DPRINT(("Processing element mask"));
476 OWF_ASSERT(&element->mask);
477 OWF_ASSERT(&element->mask->streamHandle);
478 image = element->mask->lockedStream.image;
481 state->originalMaskImage = element->mask->lockedStream.image;
483 imgf.pixelFormat = OWF_IMAGE_L32;
484 imgf.linear = image->format.linear;
485 imgf.premultiplied = image->format.premultiplied;
487 /* mask size is always same as destination rect's */
488 DPRINT(("Binding stream image to scratch buffer"));
489 CREATE_WITH_LIMITS(state->maskImage,
490 state->scaledSrcRect.width,
491 state->scaledSrcRect.height,
493 MAX_SOURCE_WIDTH, MAX_SOURCE_HEIGHT);
495 /* initialize mask */
496 DPRINT(("Initializing mask, size = %dx%d", state->scaledSrcRect.width,
497 state->scaledSrcRect.height));
498 pix = (OWFsubpixel*) state->maskImage->data;
499 for (i = 0; i < state->scaledSrcRect.width * state->scaledSrcRect.height; i++)
501 pix[i] = OWF_FULLY_OPAQUE;
506 state->originalMaskImage=NULL;
509 WFC_Pipeline_BlendInfo(context, state);
511 DPRINT((" Cropped source image size is %dx%d",
512 state->croppedSourceImage->width, state->croppedSourceImage->height));
513 DPRINT((" Scaled source image size is %dx%d",
514 state->scaledSourceImage->width, state->scaledSourceImage->height));
515 DPRINT((" Mirrored source intermediate image size is %dx%d",
516 state->rotatedSourceIntermediateImage->width, state->rotatedSourceIntermediateImage->height));
517 DPRINT((" Mirrored source image size is %dx%d",
518 state->flippedSourceImage->width, state->flippedSourceImage->height));
519 DPRINT((" Rotated source image size is %dx%d",
520 state->rotatedSourceImage->width, state->rotatedSourceImage->height));
525 /*---------------------------------------------------------------------------
526 * Composition pipeline cleanup
528 * \param context Context
529 * \param element Element
530 *----------------------------------------------------------------------------*/
532 WFC_Pipeline_EndComposition(WFC_CONTEXT* context, WFC_ELEMENT* element, WFC_ELEMENT_STATE* state)
535 if (!context || !element)
537 DPRINT(("WFC_Element_EndComposition: context == NULL || "
543 state->originalSourceImage=NULL;
544 state->originalMaskImage=NULL;
548 /*---------------------------------------------------------------------------
549 * \brief Source conversion stage
551 * \param context Context
552 * \param element Element
553 *----------------------------------------------------------------------------*/
555 WFC_Pipeline_ExecuteSourceConversionStage(WFC_CONTEXT* context,
556 WFC_ELEMENT_STATE* state)
558 /* this stage could be embedded in cropping stage */
561 if (NULL == context || NULL == state)
563 DPRINT(("WFC_Context_ExecuteSourceConversionStage: context = %p, "
569 OWF_ASSERT(state->originalSourceImage);
571 OWF_Image_SourceFormatConversion(state->convertedSourceImage,
572 state->originalSourceImage);
574 /* convert mask from stream format to internal format */
575 if (state->originalMaskImage)
577 if (!OWF_Image_ConvertMask(state->maskImage, state->originalMaskImage))
579 state->originalMaskImage=NULL;
584 /*---------------------------------------------------------------------------
587 * \param context Context
588 * \param element Element
589 *----------------------------------------------------------------------------*/
591 WFC_Pipeline_ExecuteCropStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
593 OWF_RECTANGLE sourceRect,
596 DPRINT(("WFC_Pipeline_ExecuteCropStage"));
598 if (NULL == context || NULL == state)
600 DPRINT(("WFC_Context_ExecuteCropStage: context = %p, state = %p",
605 /* Source rectangle */
606 OWF_Rect_Set(&sourceRect,
607 state->oversizedCropRect.x, state->oversizedCropRect.y,
608 state->oversizedCropRect.width, state->oversizedCropRect.height);
610 /* cropped source size - supports oversized integer and 1 pixel boundary */
611 OWF_Rect_Set(&cropRect,
613 state->oversizedCropRect.width, state->oversizedCropRect.height);
615 OWF_Image_Blit(state->croppedSourceImage, &cropRect,
616 state->convertedSourceImage, &sourceRect);
620 /*---------------------------------------------------------------------------
623 * \param context Context
624 * \param element Element
625 *----------------------------------------------------------------------------*/
627 WFC_Pipeline_ExecuteFlipStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
629 OWF_FLIP_DIRECTION flipping;
631 if (NULL == context || NULL == state)
633 DPRINT(("WFC_Context_ExecuteFlipStage: context = %p, state = %p",
638 flipping = state->sourceFlip > 0.0f ? OWF_FLIP_VERTICALLY
641 OWF_Image_Flip(state->flippedSourceImage, flipping);
645 /*---------------------------------------------------------------------------
646 * \brief Rotation stage
648 * \param context Context
649 * \param element Element
650 *----------------------------------------------------------------------------*/
652 WFC_Pipeline_ExecuteRotationStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
654 OWF_ROTATION rot = OWF_ROTATION_0;
656 WFCRotation rotation;
658 if (NULL == context || NULL == state)
660 DPRINT(("WFC_Context_ExecuteRotationStage: context = %p, state = %p",
665 rotation = state->rotation;
666 DPRINT((" Element rotation = %d", rotation));
672 return; /* Rotate copies back into input buffer so just skip */
675 case WFC_ROTATION_90:
677 rot = OWF_ROTATION_90;
681 case WFC_ROTATION_180:
683 rot = OWF_ROTATION_180;
687 case WFC_ROTATION_270:
689 rot = OWF_ROTATION_270;
699 /* rotate the the image using rotatedSourceIntermediateImage */
700 OWF_Image_Rotate(state->rotatedSourceIntermediateImage,
701 state->flippedSourceImage,
704 /* blit rotated image back to original image buffer */
707 rect.width = state->rotatedSourceIntermediateImage->width;
708 rect.height = state->rotatedSourceIntermediateImage->height;
710 DPRINT((" Source image dimensions after rotation = %dx%d",
711 rect.width, rect.height));
713 OWF_Image_Blit(state->rotatedSourceImage,
715 state->rotatedSourceIntermediateImage,
720 /*---------------------------------------------------------------------------
721 * \brief Scaling stage
723 * \param context Context
724 * \param element Element
725 *----------------------------------------------------------------------------*/
727 WFC_Pipeline_ExecuteScalingStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
729 OWF_RECTANGLE scaledRect,
731 OWF_FILTERING filteringMode = OWF_FILTER_POINT_SAMPLING;
732 WFCScaleFilter filter;
734 DPRINT(("WFC_Context_ExecuteScalingStage(%p,%p)", context, state));
736 if (NULL == context || NULL == state)
738 DPRINT(("WFC_Context_ExecuteScalingStage: context = %p, state = %p",
743 filter = state->sourceScaleFilter;
747 case WFC_SCALE_FILTER_NONE:
748 case WFC_SCALE_FILTER_FASTER:
750 filteringMode = OWF_FILTER_POINT_SAMPLING;
751 DPRINT((" Using point-sampling filter"));
754 case WFC_SCALE_FILTER_BETTER:
756 filteringMode = OWF_FILTER_BILINEAR;
757 DPRINT((" Using bilinear filter"));
761 case WFC_SCALE_FILTER_FORCE_32BIT:
763 /* To shut the compiler up -- not a valid filtering mode.
764 * Validity is ensured when the filter attribute value
765 * is set, thus it shouldn't have this value ever. */
771 OWF_Rect_Set(&cropRect, 1, 1,
772 state->rotatedSourceImage->width - EXTRA_PIXEL_BOUNDARY,
773 state->rotatedSourceImage->height - EXTRA_PIXEL_BOUNDARY);
775 OWF_Rect_Set(&scaledRect, 0, 0, state->destinationRect[2], state->destinationRect[3]);
777 if ( scaledRect.width != state->transformedSourceRect[2]
778 || scaledRect.height != state->transformedSourceRect[3]
779 || state->sourceRect[0] != floor(state->sourceRect[0])
780 || state->sourceRect[1] != floor(state->sourceRect[1])
783 /* scale the image */
784 OWF_Image_Stretch(state->scaledSourceImage, &scaledRect,
785 state->rotatedSourceImage, state->transformedSourceRect,
790 /* 1:1 copy, no need to scale */
791 OWF_Image_Blit(state->scaledSourceImage, &scaledRect,
792 state->rotatedSourceImage, &cropRect);
797 /*---------------------------------------------------------------------------
798 * \brief Blending stage
800 * \param context Context
801 * \param element Element
802 *----------------------------------------------------------------------------*/
804 WFC_Pipeline_ExecuteBlendingStage(WFC_CONTEXT* context, WFC_ELEMENT_STATE* state)
806 OWF_TRANSPARENCY blendMode = OWF_TRANSPARENCY_NONE;
807 WFCbitfield transparency = 0;
809 DPRINT(("WFC_Pipeline_ExecuteBlendingStage"));
811 if (NULL == context || NULL == state)
816 DPRINT((" context = %d, state = %d",
817 context->handle, state));
819 transparency = state->transparencyTypes;
820 blendMode = OWF_TRANSPARENCY_NONE;
822 if (transparency & WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA)
824 blendMode = (OWF_TRANSPARENCY)(blendMode|OWF_TRANSPARENCY_GLOBAL_ALPHA);
827 if (transparency & WFC_TRANSPARENCY_SOURCE)
829 OWF_Image_PremultiplyAlpha(state->scaledSourceImage);
830 blendMode = (OWF_TRANSPARENCY)(blendMode|OWF_TRANSPARENCY_SOURCE_ALPHA);
833 if ((transparency & WFC_TRANSPARENCY_MASK) && state->originalMaskImage)
835 blendMode = (OWF_TRANSPARENCY)(blendMode|OWF_TRANSPARENCY_MASK);
838 OWF_Image_Blend(&state->blendInfo, blendMode);