109 /* internal image used as intermediate target */ |
110 /* internal image used as intermediate target */ |
110 fInt.pixelFormat = OWF_IMAGE_ARGB_INTERNAL; |
111 fInt.pixelFormat = OWF_IMAGE_ARGB_INTERNAL; |
111 fInt.linear = fExt.linear; |
112 fInt.linear = fExt.linear; |
112 fInt.premultiplied = fExt.premultiplied; |
113 fInt.premultiplied = fExt.premultiplied; |
113 fInt.rowPadding = 1; |
114 fInt.rowPadding = 1; |
|
115 |
114 |
116 |
115 if (context->type == WFC_CONTEXT_TYPE_ON_SCREEN) |
117 if (context->type == WFC_CONTEXT_TYPE_ON_SCREEN) |
116 { |
118 { |
117 /* The unrotated target buffer: Can't get real address without locking for writing! NO STRIDE */ |
119 /* The unrotated target buffer: Can't get real address without locking for writing! NO STRIDE */ |
118 context->state.unrotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fExt,context->scratchBuffer[2],0); |
120 context->state.unrotatedTargetImage=OWF_Image_Create(context->targetWidth,context->targetHeight,&fExt,context->scratchBuffer[2],0); |
119 /* The rotated version of the target buffer for hardware rotation |
121 /* The rotated version of the target buffer for hardware rotation |
120 * or a de-rotated version of the internal buffer into another scratch buffer for software rotation |
122 * or a de-rotated version of the internal buffer into another scratch buffer for software rotation |
121 */ |
123 */ |
122 if (OWF_Screen_Rotation_Supported(context->displayContext)) |
124 if (OWF_Screen_Rotation_Supported(context->screenNumber)) |
123 { /* The rotated version of the target buffer for hardware rotation */ |
125 { /* The rotated version of the target buffer for hardware rotation */ |
124 context->state.rotatedTargetImage=OWF_Image_Create(context->targetHeight,context->targetWidth,&fExt,context->scratchBuffer[2],0); |
126 context->state.rotatedTargetImage=OWF_Image_Create(context->targetHeight,context->targetWidth,&fExt,context->scratchBuffer[2],0); |
125 } |
127 } |
126 else |
128 else |
127 { /* a de-rotated version of the internal buffer into another scratch buffer for software rotation */ |
129 { /* a de-rotated version of the internal buffer into another scratch buffer for software rotation */ |
370 { |
359 { |
371 DPRINT(("WFC_Context_Initialize(): Missing EGL extension - egl_Private_SignalSyncNOK extension")); |
360 DPRINT(("WFC_Context_Initialize(): Missing EGL extension - egl_Private_SignalSyncNOK extension")); |
372 return NULL; |
361 return NULL; |
373 } |
362 } |
374 |
363 |
375 err2 =OWF_MessageQueue_Init(&context->composerQueue); |
364 /*the following section of the code could be pushed to adaptation in future*/ |
376 if (err2 != 0) |
|
377 { |
|
378 DPRINT(("WFC_Context_Initialize(): Cannot initialise the message queue err(%d)", err2)); |
|
379 return NULL; |
|
380 } |
|
381 |
|
382 context->composerThread = OWF_Thread_Create(WFC_Context_ComposerThread, context); |
|
383 if (!(context->composerThread)) |
|
384 { |
|
385 /* must call these to remove references to context */ |
|
386 DPRINT(("WFC_Context_Initialize(): Failed to create thread!")); |
|
387 return NULL; |
|
388 } |
|
389 |
|
390 OWF_ComposerThread_RendezvousWait(context->displayContext); |
|
391 |
|
392 /*the following section of the code could be pushed to adaptation in future*/ |
|
393 if (type == WFC_CONTEXT_TYPE_ON_SCREEN) |
365 if (type == WFC_CONTEXT_TYPE_ON_SCREEN) |
394 { |
366 { |
395 OWF_IMAGE_FORMAT imageFormat; |
367 OWF_IMAGE_FORMAT imageFormat; |
396 OWF_SCREEN screen; |
368 OWF_SCREEN screen; |
397 WFCint width = 0; |
369 WFCint width = 0; |
398 WFCint height = 0; |
370 WFCint height = 0; |
399 WFCint normalSize = 0; |
371 WFCint normalSize = 0; |
400 WFCint flippedSize = 0; |
372 WFCint flippedSize = 0; |
401 WFCNativeStreamType stream; |
373 WFCNativeStreamType stream; |
402 |
374 |
403 /* Set up stream for sending data to screen */ |
375 /* Set up stream for sending data to screen */ |
404 |
376 |
405 if (!OWF_Screen_GetHeader(context->displayContext, &screen)) |
377 if (!OWF_Screen_GetHeader(screenNum, &screen)) |
406 { |
378 { |
407 DPRINT(("WFC_Context_Initialize(): Could not retrieve the screen parameters")); |
379 DPRINT(("WFC_Context_Initialize(): Could not retrieve the screen parameters")); |
408 WFC_Context_Shutdown(context); |
380 return NULL; |
409 return NULL; |
381 } |
410 } |
382 |
411 |
383 /* Set on-screen pixel format */ |
412 /* Set on-screen pixel format */ |
384 imageFormat.pixelFormat = OWF_SURFACE_PIXEL_FORMAT; |
413 imageFormat.pixelFormat = OWF_SURFACE_PIXEL_FORMAT; |
385 imageFormat.premultiplied = OWF_SURFACE_PREMULTIPLIED; |
414 imageFormat.premultiplied = OWF_SURFACE_PREMULTIPLIED; |
386 imageFormat.linear = OWF_SURFACE_LINEAR; |
415 imageFormat.linear = OWF_SURFACE_LINEAR; |
387 imageFormat.rowPadding = OWF_SURFACE_ROWPADDING; |
416 imageFormat.rowPadding = OWF_SURFACE_ROWPADDING; |
388 |
417 |
389 width = screen.normal.width; |
418 width = screen.normal.width; |
390 height = screen.normal.height; |
419 height = screen.normal.height; |
391 |
420 |
392 normalSize = screen.normal.height * screen.normal.stride; |
421 normalSize = screen.normal.height * screen.normal.stride; |
393 flippedSize = screen.flipped.height * screen.flipped.stride; |
422 flippedSize = screen.flipped.height * screen.flipped.stride; |
394 |
423 |
395 if (flippedSize > normalSize) |
424 if (flippedSize > normalSize) |
396 { |
425 { |
397 width = screen.flipped.width; |
426 width = screen.flipped.width; |
398 height = screen.flipped.height; |
427 height = screen.flipped.height; |
399 } |
428 } |
400 |
429 |
401 stream = owfNativeStreamCreateImageStream(width, |
430 stream = owfNativeStreamCreateImageStream(width, |
402 height, |
431 height, |
403 &imageFormat, |
432 &imageFormat, |
404 1); |
433 1); |
405 |
434 |
406 if (stream) |
435 if (stream) |
407 { |
436 { |
408 WFC_Context_SetTargetStream(context, stream); |
437 WFC_Context_SetTargetStream(context, stream); |
409 |
438 |
410 /* At this point the stream's refcount is 2 - we must decrement |
439 /* At this point the stream's refcount is 2 - we must decrement |
411 * it by one to ensure that the stream is destroyed when the |
440 * it by one to ensure that the stream is destroyed when the |
412 * context (that "owns" it) is destroyed. |
441 * context (that "owns" it) is destroyed. |
413 */ |
442 */ |
414 owfNativeStreamRemoveReference(stream); |
443 owfNativeStreamRemoveReference(stream); |
415 } |
444 } |
416 else |
445 else |
417 { |
446 { |
418 DPRINT(("WFC_Context_Initialize(): cannot create internal target stream")); |
447 DPRINT(("WFC_Context_Initialize(): cannot create internal target stream")); |
419 return NULL; |
448 WFC_Context_Shutdown(context); |
420 } |
449 return NULL; |
|
450 } |
|
451 } |
421 } |
452 else |
422 else |
453 { |
423 { |
454 WFC_Context_SetTargetStream(context, stream); |
424 WFC_Context_SetTargetStream(context, stream); |
455 } |
425 } |
456 |
426 |
457 nbufs = SCRATCH_BUFFER_COUNT-1; |
427 nbufs = SCRATCH_BUFFER_COUNT-1; |
458 for (ii = 0; ii < nbufs; ii++) |
428 for (ii = 0; ii < nbufs; ii++) |
459 { |
429 { |
470 scratch[nbufs] = OWF_Image_AllocData(context->displayContext, MAX_SOURCE_WIDTH, |
440 scratch[nbufs] = OWF_Image_AllocData(context->displayContext, MAX_SOURCE_WIDTH, |
471 MAX_SOURCE_HEIGHT, |
441 MAX_SOURCE_HEIGHT, |
472 OWF_IMAGE_L32); |
442 OWF_IMAGE_L32); |
473 fail = fail || (scratch[nbufs] == NULL); |
443 fail = fail || (scratch[nbufs] == NULL); |
474 |
444 |
|
445 err2 = OWF_MessageQueue_Init(&context->composerQueue); |
|
446 fail = fail || (err2 != 0); |
|
447 |
475 if (fail) |
448 if (fail) |
476 { |
449 { |
|
450 OWF_MessageQueue_Destroy(&context->composerQueue); |
|
451 |
477 for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++) |
452 for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++) |
478 { |
453 { |
479 OWF_Image_FreeData(context->displayContext, &scratch[ii]); |
454 OWF_Image_FreeData(context->displayContext, &scratch[ii]); |
480 } |
455 } |
481 WFC_Context_Shutdown(context); |
|
482 return NULL; |
456 return NULL; |
483 } |
457 } |
484 |
458 |
485 for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++) |
459 for (ii = 0; ii < SCRATCH_BUFFER_COUNT; ii++) |
486 { |
460 { |
487 context->scratchBuffer[ii] = scratch[ii]; |
461 context->scratchBuffer[ii] = scratch[ii]; |
488 } |
462 } |
489 |
463 |
|
464 if (!WFC_Pipeline_CreateState(context) || !WFC_Context_CreateState(context)) |
|
465 { |
|
466 DPRINT(("WFC_Context_Initialize(): Could not create pipeline state object")); |
|
467 return NULL; |
|
468 } |
490 if ( OWF_Semaphore_Init(&context->compositionSemaphore, 1) |
469 if ( OWF_Semaphore_Init(&context->compositionSemaphore, 1) |
491 || OWF_Semaphore_Init(&context->commitSemaphore, 1) |
470 || OWF_Semaphore_Init(&context->commitSemaphore, 1) |
492 || OWF_Mutex_Init(&context->updateFlagMutex) |
471 || OWF_Mutex_Init(&context->updateFlagMutex) |
493 || OWF_Mutex_Init(&context->sceneMutex) |
472 || OWF_Mutex_Init(&context->sceneMutex) |
494 |
473 |
495 ) |
474 ) |
496 { |
475 { |
497 DPRINT(("WFC_Context_Initialize(): Could not create mutexes and semaphores!")); |
476 DPRINT(("WFC_Context_Initialize(): Could not create mutexes and semaphores!")); |
498 WFC_Context_Shutdown(context); |
|
499 return NULL; |
477 return NULL; |
500 } |
478 } |
501 |
479 |
502 if (!WFC_Pipeline_CreateState(context) || !WFC_Context_CreateState(context)) |
|
503 { |
|
504 DPRINT(("WFC_Context_Initialize(): Could not create pipeline state object")); |
|
505 WFC_Context_Shutdown(context); |
|
506 return NULL; |
|
507 } |
|
508 |
|
509 |
|
510 attribStatus= WFC_Context_InitializeAttributes(context, type); |
480 attribStatus= WFC_Context_InitializeAttributes(context, type); |
511 |
481 |
512 if (attribStatus!=ATTR_ERROR_NONE) |
482 if (attribStatus!=ATTR_ERROR_NONE) |
513 { |
483 { |
514 WFC_Context_Shutdown(context); |
|
515 return NULL; |
484 return NULL; |
516 } |
485 } |
517 |
486 |
518 |
487 |
519 context->scenePool = OWF_Pool_Create(sizeof(WFC_SCENE), |
488 context->scenePool = OWF_Pool_Create(sizeof(WFC_SCENE), |
594 |
582 |
595 owfNativeStreamGetHeader(stream, |
583 owfNativeStreamGetHeader(stream, |
596 &context->targetWidth, &context->targetHeight, |
584 &context->targetWidth, &context->targetHeight, |
597 NULL, NULL, NULL); |
585 NULL, NULL, NULL); |
598 } |
586 } |
599 |
|
600 static OWFboolean |
|
601 WFC_FastpathCheckTransparency(WFCbitfield transparencyTypes, WFCfloat globalAlpha, OWF_PIXEL_FORMAT sourceFormat) |
|
602 { |
|
603 if ((transparencyTypes & WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA) && (globalAlpha != 255.0f)) |
|
604 { |
|
605 DPRINT(("=== WFC_FastpathCheckTransparency - Failed global alfa(%f) check", globalAlpha)); |
|
606 return OWF_FALSE; |
|
607 } |
|
608 |
|
609 if ((transparencyTypes & WFC_TRANSPARENCY_SOURCE) && (sourceFormat != OWF_IMAGE_XRGB8888)) |
|
610 { |
|
611 DPRINT(("=== WFC_FastpathCheckTransparency - Failed transparency check types=0x%x format=0x%x", |
|
612 transparencyTypes, sourceFormat)); |
|
613 return OWF_FALSE; |
|
614 } |
|
615 |
|
616 |
|
617 return OWF_TRUE; |
|
618 } |
|
619 |
|
620 static OWFboolean |
|
621 WFC_FastpathCheckGeometry(WFC_CONTEXT* context, WFC_ELEMENT* element) |
|
622 { |
|
623 OWFint sourceWidth = 0; |
|
624 OWFint sourceHeight = 0; |
|
625 OWFint destWidth = 0; |
|
626 OWFint destHeight = 0; |
|
627 OWFint targetWidth = 0; |
|
628 OWFint targetHeight = 0; |
|
629 |
|
630 OWF_ASSERT(context); |
|
631 OWF_ASSERT(element); |
|
632 |
|
633 if ((element->srcRect[0] != 0) || (element->srcRect[1] != 0)) |
|
634 { |
|
635 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Source Position Check", context)); |
|
636 return OWF_FALSE; |
|
637 } |
|
638 |
|
639 if ((element->dstRect[0] != 0) || (element->dstRect[1] != 0)) |
|
640 { |
|
641 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Destination Position Check", context)); |
|
642 return OWF_FALSE; |
|
643 } |
|
644 |
|
645 if(element->sourceFlip) |
|
646 { |
|
647 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Source Flip Check", context)); |
|
648 return OWF_FALSE; |
|
649 } |
|
650 |
|
651 if(element->sourceRotation == WFC_ROTATION_0) |
|
652 { |
|
653 sourceWidth = element->srcRect[2]; |
|
654 sourceHeight = element->srcRect[3]; |
|
655 } |
|
656 else |
|
657 { |
|
658 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Source Rotation (0x%x) Check", |
|
659 context, element->sourceRotation)); |
|
660 return OWF_FALSE; |
|
661 } |
|
662 |
|
663 destWidth = element->dstRect[2]; |
|
664 destHeight = element->dstRect[3]; |
|
665 |
|
666 if ((sourceWidth != destWidth) || (sourceHeight != destHeight)) |
|
667 { |
|
668 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - FAILED Non-scaling Check", context)); |
|
669 return OWF_FALSE; |
|
670 } |
|
671 |
|
672 if (context->rotation == WFC_ROTATION_0 || OWF_Screen_Rotation_Supported(context->displayContext)) |
|
673 { |
|
674 if (context->rotation == WFC_ROTATION_0 || context->rotation == WFC_ROTATION_180) |
|
675 { |
|
676 targetWidth = context->targetWidth; |
|
677 targetHeight = context->targetHeight; |
|
678 } |
|
679 else |
|
680 { |
|
681 targetWidth = context->targetHeight; |
|
682 targetHeight = context->targetWidth; |
|
683 } |
|
684 |
|
685 if (destWidth == targetWidth && destHeight == targetHeight) |
|
686 { |
|
687 return OWF_TRUE; |
|
688 } |
|
689 else |
|
690 { |
|
691 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - Failed Dimensions Check", context)); |
|
692 } |
|
693 } |
|
694 else |
|
695 { |
|
696 DPRINT(("=== WFC_FastpathCheckGeometry(context = %p) - Failed Supported Rotations Check", context)); |
|
697 } |
|
698 |
|
699 return OWF_FALSE; |
|
700 } |
|
701 |
|
702 /** |
|
703 * Check if the current scene is candidate for fastpath optimisation. |
|
704 * Fastpath optimisation means the topmost visible layer will be passed direct to the |
|
705 * lower level for presentation on the display without being composed. |
|
706 * There are two questions: |
|
707 * - Is the scene itself suitable for fastpathing? |
|
708 * - Can the surface selected for fastpathing be presented directly by the display? |
|
709 * This function will check the scene (eg reject if the top stream is non-opaque or smaller than the screen) |
|
710 * |
|
711 * @param context context object containing the scene to be checked. |
|
712 **/ |
|
713 |
|
714 /* [Not in doxygen] |
|
715 * The first time MOpenWFC_RI_Display_Update::SetTopLayerSurface (or SetLayerSurface) is called |
|
716 * with a different stream handle, it can fail indicating the display cannot accept the stream. |
|
717 * The compositor will then have to immediately compose that frame as normal, and should continue |
|
718 * to perform normal composition until the scene changes to present a different stream as fastpath candidate. |
|
719 * |
|
720 * There is a middle ground, e.g. can the hardware handle over-sized images, or do scaling or do rotation? |
|
721 * SetTopLayerSurface accepts an optional list of imperfect attributes to be checked by the adaptation. |
|
722 * By WFC_Context_CheckFastpath only listing the attributes that are considered imperfect, |
|
723 * and SetLayerSurface rejecting fastpath for any attribute IDs that it doesn't recognise, |
|
724 * safe independent extensibility is assured. |
|
725 */ |
|
726 static void |
|
727 WFC_Context_CheckFastpath(WFC_CONTEXT* context) |
|
728 { |
|
729 WFC_ELEMENT* element = NULL; |
|
730 OWF_ASSERT(context); |
|
731 |
|
732 DPRINT(("WFC_Context_CheckFastpath(context = %p) - Check Fastpath", context)); |
|
733 if ((context->type != WFC_CONTEXT_TYPE_ON_SCREEN) || |
|
734 OWF_DisplayContext_FastpathChecked(context->displayContext)) |
|
735 { |
|
736 return; |
|
737 } |
|
738 |
|
739 // Simple case-fast path top most layer |
|
740 // More complex case, fast-path top most VISIBLE, OPAQUE layer. |
|
741 OWF_DisplayContext_DisableFastpath(context->displayContext); |
|
742 OWF_DisplayContext_SetFastpathChecked(context->displayContext); |
|
743 // Find top layer |
|
744 element = WFC_Scene_TopMostElement(context->committedScene); |
|
745 if (element && element->source && element->skipCompose == WFC_FALSE) |
|
746 { |
|
747 |
|
748 if (element->mask) |
|
749 { |
|
750 DPRINT(("=== WFC_Context_CheckFastpath(context = %p) - FAILED elemenent includes mask", context)); |
|
751 return; |
|
752 } |
|
753 |
|
754 OWF_ASSERT(element->source->lockedStream.image); |
|
755 |
|
756 OWF_ASSERT(element->source->streamHandle != OWF_INVALID_HANDLE); |
|
757 |
|
758 if (!WFC_FastpathCheckGeometry(context, element)) |
|
759 { |
|
760 return; |
|
761 } |
|
762 |
|
763 if (!WFC_FastpathCheckTransparency(element->transparencyTypes, |
|
764 element->globalAlpha, |
|
765 element->source->lockedStream.image->format.pixelFormat)) |
|
766 { |
|
767 return; |
|
768 } |
|
769 |
|
770 OWF_DisplayContext_EnableFastpath(context->displayContext, element->source->streamHandle); |
|
771 DPRINT(("=== WFC_Context_CheckFastpath(context = %p) - Fastpath Enabled", context)); |
|
772 } |
|
773 } |
|
774 |
|
775 /*--------------------------------------------------------------------------- |
587 /*--------------------------------------------------------------------------- |
776 * Checks if the given stream would be valid as an off-screen context target. |
588 * Checks if the given stream would be valid as an off-screen context target. |
777 * |
589 * |
778 * Checks that the format can be rendered TO. |
590 * Checks that the format can be rendered TO. |
779 * Also checks that the image size is acceptable (within the scratch buffers). |
591 * Also checks that the image size is acceptable (within the scratch buffers). |
886 } |
698 } |
887 |
699 |
888 /*--------------------------------------------------------------------------- |
700 /*--------------------------------------------------------------------------- |
889 * |
701 * |
890 *----------------------------------------------------------------------------*/ |
702 *----------------------------------------------------------------------------*/ |
891 static OWFboolean |
703 static void |
892 WFC_Context_LockTargetForWriting(WFC_CONTEXT* context) |
704 WFC_Context_LockTargetForWriting(WFC_CONTEXT* context) |
893 { |
705 { |
894 OWF_ASSERT(context); |
706 OWF_ASSERT(context); |
895 |
707 |
896 DPRINT(("WFC_Context_LockTargetForWriting")); |
708 DPRINT(("WFC_Context_LockTargetForWriting")); |
897 |
709 |
898 context->state.targetBuffer = |
710 context->state.targetBuffer = |
899 owfNativeStreamAcquireWriteBuffer(context->stream); |
711 owfNativeStreamAcquireWriteBuffer(context->stream); |
900 |
|
901 if (!context->state.targetBuffer) |
|
902 { |
|
903 DPRINT(("Failed to WFC_Context_LockTargetForWriting owfNativeStreamAcquireWriteBuffer")); |
|
904 return OWF_FALSE; |
|
905 } |
|
906 context->state.targetPixels = |
712 context->state.targetPixels = |
907 owfNativeStreamGetBufferPtr(context->stream, |
713 owfNativeStreamGetBufferPtr(context->stream, |
908 context->state.targetBuffer); |
714 context->state.targetBuffer); |
909 |
715 |
910 if ((WFC_ROTATION_0 == context->rotation || WFC_ROTATION_180 == context->rotation) || |
716 if ((WFC_ROTATION_0 == context->rotation || WFC_ROTATION_180 == context->rotation) || |
911 !OWF_Screen_Rotation_Supported(context->displayContext)) |
717 !OWF_Screen_Rotation_Supported(context->screenNumber)) |
912 { |
718 { |
913 /* final target, in target format */ |
719 /* final target, in target format */ |
914 context->state.targetImage =context->state.unrotatedTargetImage; |
720 context->state.targetImage =context->state.unrotatedTargetImage; |
915 } |
721 } |
916 else |
722 else |
961 context->state.targetBuffer, |
768 context->state.targetBuffer, |
962 EGL_NO_DISPLAY, |
769 EGL_NO_DISPLAY, |
963 NULL); |
770 NULL); |
964 |
771 |
965 |
772 |
966 if (aDoPost) |
773 /* Refactor the code that follows so that it is triggered by the above releasewrite */ |
|
774 |
|
775 /* Acquire target stream front buffer and blit to SDL screen */ |
|
776 frontBuffer = owfNativeStreamAcquireReadBuffer(context->stream); |
|
777 DPRINT((" Locking target stream=%d, buffer=%d", |
|
778 context->stream, frontBuffer)); |
|
779 |
|
780 pixelDataPtr = owfNativeStreamGetBufferPtr(context->stream, frontBuffer); |
|
781 |
|
782 switch (context->rotation) |
|
783 { |
|
784 case WFC_ROTATION_0: |
|
785 { |
|
786 rotation = OWF_ROTATION_0; |
|
787 break; |
|
788 } |
|
789 case WFC_ROTATION_90: |
|
790 { |
|
791 rotation = OWF_ROTATION_90; |
|
792 break; |
|
793 } |
|
794 case WFC_ROTATION_180: |
|
795 { |
|
796 rotation = OWF_ROTATION_180; |
|
797 break; |
|
798 } |
|
799 case WFC_ROTATION_270: |
|
800 { |
|
801 rotation = OWF_ROTATION_270; |
|
802 break; |
|
803 } |
|
804 default: |
|
805 { |
|
806 OWF_ASSERT(0); |
|
807 } |
|
808 } |
|
809 |
|
810 OWF_Screen_Blit(context->screenNumber, pixelDataPtr, rotation); |
|
811 |
|
812 owfNativeStreamReleaseReadBuffer(context->stream, frontBuffer); |
|
813 DPRINT((" Releasing target stream=%d, buffer=%d", |
|
814 context->stream, frontBuffer)); |
|
815 |
|
816 } |
|
817 |
|
818 /*--------------------------------------------------------------------------- |
|
819 * |
|
820 *----------------------------------------------------------------------------*/ |
|
821 static void |
|
822 WFC_Context_PrepareComposition(WFC_CONTEXT* context) |
|
823 { |
|
824 OWFsubpixel r, g, b, a; |
|
825 |
|
826 OWF_ASSERT(context); |
|
827 |
|
828 /* the first thing to do is to lock target stream and fetch |
|
829 write buffer to it. fetching blocks until one is available, |
|
830 but since only one stream can be target to only one context |
|
831 at the time, no stalls should occur */ |
|
832 WFC_Context_LockTargetForWriting(context); |
|
833 |
|
834 /* prepare for composition by "clearing the table" with |
|
835 background color. */ |
|
836 |
|
837 r = (OWFsubpixel) OWF_RED_MAX_VALUE * ((context->backgroundColor >> 24) & |
|
838 0xFF) / OWF_BYTE_MAX_VALUE; |
|
839 g = (OWFsubpixel) OWF_GREEN_MAX_VALUE * ((context->backgroundColor >> 16) & |
|
840 0xFF) / OWF_BYTE_MAX_VALUE; |
|
841 b = (OWFsubpixel) OWF_BLUE_MAX_VALUE * ((context->backgroundColor >> 8) & |
|
842 0xFF) / OWF_BYTE_MAX_VALUE; |
|
843 a = (OWFsubpixel) OWF_ALPHA_MAX_VALUE * (context->backgroundColor & 0xFF) / |
|
844 OWF_BYTE_MAX_VALUE; |
|
845 |
|
846 r = r * a / OWF_ALPHA_MAX_VALUE; |
|
847 g = g * a / OWF_ALPHA_MAX_VALUE; |
|
848 b = b * a / OWF_ALPHA_MAX_VALUE; |
|
849 |
|
850 OWF_Image_Clear(context->state.internalTargetImage, r, g, b, a); |
|
851 |
|
852 WFC_Scene_LockSourcesAndMasks(context->committedScene); |
|
853 } |
|
854 |
|
855 |
|
856 |
|
857 /*--------------------------------------------------------------------------- |
|
858 * |
|
859 *----------------------------------------------------------------------------*/ |
|
860 static void |
|
861 WFC_Context_FinishComposition(WFC_CONTEXT* context) |
|
862 { |
|
863 OWF_ROTATION rotation = OWF_ROTATION_0; |
|
864 OWFint screenNumber; |
|
865 OWFboolean screenRotation; |
|
866 |
|
867 OWF_ASSERT(context); |
|
868 |
|
869 screenNumber = context->screenNumber; |
|
870 screenRotation = OWF_Screen_Rotation_Supported(screenNumber); |
|
871 /* re-use scratch buffer 1 for context rotation */ |
|
872 if (WFC_ROTATION_0 == context->rotation || screenRotation) |
|
873 { |
|
874 |
|
875 if (screenRotation) |
|
876 { |
|
877 if (WFC_ROTATION_90 == context->rotation || WFC_ROTATION_270 == context->rotation) |
|
878 { |
|
879 owfSetStreamFlipState(context->stream, OWF_TRUE); |
|
880 } |
|
881 else |
|
882 { |
|
883 owfSetStreamFlipState(context->stream, OWF_FALSE); |
|
884 } |
|
885 } |
|
886 OWF_Image_DestinationFormatConversion(context->state.targetImage, context->state.internalTargetImage); |
|
887 } |
|
888 else |
967 { |
889 { |
968 switch (context->rotation) |
890 switch (context->rotation) |
969 { |
891 { |
970 case WFC_ROTATION_0: |
892 case WFC_ROTATION_0: |
971 { |
893 { |
990 default: |
912 default: |
991 { |
913 { |
992 OWF_ASSERT(0); |
914 OWF_ASSERT(0); |
993 } |
915 } |
994 } |
916 } |
995 |
|
996 if (!OWF_Screen_Post_Topmost_Layer(context->displayContext, context->stream, rotation)) |
|
997 { //getting a fail here is bad... display did not accept the composition buffer. |
|
998 DPRINT(("WFC_Context_UnlockTarget - OWF_Screen_Post_Topmost_Layer failed for composition stream")); |
|
999 OWF_ASSERT(0); |
|
1000 } |
|
1001 } |
|
1002 } |
|
1003 |
|
1004 /*--------------------------------------------------------------------------- |
|
1005 * |
|
1006 *----------------------------------------------------------------------------*/ |
|
1007 static void |
|
1008 WFC_Context_PrepareComposition(WFC_CONTEXT* context) |
|
1009 { |
|
1010 OWFsubpixel r, g, b, a; |
|
1011 |
|
1012 OWF_ASSERT(context); |
|
1013 |
|
1014 /* the first thing to do is to lock target stream and fetch |
|
1015 write buffer to it. fetching blocks until one is available, |
|
1016 but since only one stream can be target to only one context |
|
1017 at the time, no stalls should occur */ |
|
1018 WFC_Context_LockTargetForWriting(context); |
|
1019 |
|
1020 /* prepare for composition by "clearing the table" with |
|
1021 background color. */ |
|
1022 |
|
1023 r = (OWFsubpixel) OWF_RED_MAX_VALUE * ((context->backgroundColor >> 24) & |
|
1024 0xFF) / OWF_BYTE_MAX_VALUE; |
|
1025 g = (OWFsubpixel) OWF_GREEN_MAX_VALUE * ((context->backgroundColor >> 16) & |
|
1026 0xFF) / OWF_BYTE_MAX_VALUE; |
|
1027 b = (OWFsubpixel) OWF_BLUE_MAX_VALUE * ((context->backgroundColor >> 8) & |
|
1028 0xFF) / OWF_BYTE_MAX_VALUE; |
|
1029 a = (OWFsubpixel) OWF_ALPHA_MAX_VALUE * (context->backgroundColor & 0xFF) / |
|
1030 OWF_BYTE_MAX_VALUE; |
|
1031 |
|
1032 r = r * a / OWF_ALPHA_MAX_VALUE; |
|
1033 g = g * a / OWF_ALPHA_MAX_VALUE; |
|
1034 b = b * a / OWF_ALPHA_MAX_VALUE; |
|
1035 |
|
1036 OWF_Image_Clear(context->state.internalTargetImage, r, g, b, a); |
|
1037 } |
|
1038 |
|
1039 |
|
1040 |
|
1041 /*--------------------------------------------------------------------------- |
|
1042 * |
|
1043 *----------------------------------------------------------------------------*/ |
|
1044 static void |
|
1045 WFC_Context_FinishComposition(WFC_CONTEXT* context) |
|
1046 { |
|
1047 OWF_ROTATION rotation = OWF_ROTATION_0; |
|
1048 OWFboolean screenRotation; |
|
1049 |
|
1050 OWF_ASSERT(context); |
|
1051 |
|
1052 screenRotation = OWF_Screen_Rotation_Supported(context->displayContext); |
|
1053 /* re-use scratch buffer 1 for context rotation */ |
|
1054 if (WFC_ROTATION_0 == context->rotation || screenRotation) |
|
1055 { |
|
1056 |
|
1057 if (screenRotation) |
|
1058 { |
|
1059 if (WFC_ROTATION_90 == context->rotation || WFC_ROTATION_270 == context->rotation) |
|
1060 { |
|
1061 owfSetStreamFlipState(context->stream, OWF_TRUE); |
|
1062 } |
|
1063 else |
|
1064 { |
|
1065 owfSetStreamFlipState(context->stream, OWF_FALSE); |
|
1066 } |
|
1067 } |
|
1068 OWF_Image_DestinationFormatConversion(context->state.targetImage, context->state.internalTargetImage); |
|
1069 } |
|
1070 else |
|
1071 { |
|
1072 switch (context->rotation) |
|
1073 { |
|
1074 case WFC_ROTATION_0: |
|
1075 { |
|
1076 rotation = OWF_ROTATION_0; |
|
1077 break; |
|
1078 } |
|
1079 case WFC_ROTATION_90: |
|
1080 { |
|
1081 rotation = OWF_ROTATION_90; |
|
1082 break; |
|
1083 } |
|
1084 case WFC_ROTATION_180: |
|
1085 { |
|
1086 rotation = OWF_ROTATION_180; |
|
1087 break; |
|
1088 } |
|
1089 case WFC_ROTATION_270: |
|
1090 { |
|
1091 rotation = OWF_ROTATION_270; |
|
1092 break; |
|
1093 } |
|
1094 default: |
|
1095 { |
|
1096 OWF_ASSERT(0); |
|
1097 } |
|
1098 } |
|
1099 |
917 |
1100 /* rotate */ |
918 /* rotate */ |
1101 OWF_Image_Rotate(context->state.rotatedTargetImage, |
919 OWF_Image_Rotate(context->state.rotatedTargetImage, |
1102 context->state.internalTargetImage, |
920 context->state.internalTargetImage, |
1103 rotation); |
921 rotation); |
1104 |
922 |
1105 /* Note: support of different target formats can be put here */ |
923 /* Note: support of different target formats can be put here */ |
1106 |
924 |
1107 OWF_Image_DestinationFormatConversion(context->state.targetImage, context->state.rotatedTargetImage); |
925 OWF_Image_DestinationFormatConversion(context->state.targetImage, context->state.rotatedTargetImage); |
1108 } |
926 } |
1109 WFC_Context_UnlockTarget(context,(context->type==WFC_CONTEXT_TYPE_ON_SCREEN)?OWF_TRUE:OWF_FALSE); |
927 WFC_Context_UnlockTarget(context); |
|
928 WFC_Scene_UnlockSourcesAndMasks(context->committedScene); |
1110 } |
929 } |
1111 |
930 |
1112 /*!--------------------------------------------------------------------------- |
931 /*!--------------------------------------------------------------------------- |
1113 * \brief Actual composition routine. |
932 * \brief Actual composition routine. |
1114 * Mainly just calls other functions that executes different stages of |
933 * Mainly just calls other functions that executes different stages of |
1129 |
948 |
1130 OWF_DisplayContext_SetCompositionOngoing(context->displayContext, WFC_TRUE); |
949 OWF_DisplayContext_SetCompositionOngoing(context->displayContext, WFC_TRUE); |
1131 context->sourceUpdateCount = 0; |
950 context->sourceUpdateCount = 0; |
1132 OWF_Mutex_Unlock(&context->updateFlagMutex); |
951 OWF_Mutex_Unlock(&context->updateFlagMutex); |
1133 |
952 |
|
953 WFC_Context_PrepareComposition(context); |
|
954 |
1134 DPRINT(("WFC_Context_Compose")); |
955 DPRINT(("WFC_Context_Compose")); |
1135 /* Composition always uses the committed version |
956 /* Composition always uses the committed version |
1136 * of the scene. |
957 * of the scene. |
1137 */ |
958 */ |
1138 |
959 |
1139 WFC_Scene_LockSourcesAndMasks(context->committedScene); |
|
1140 |
|
1141 OWF_Mutex_Lock(&context->sceneMutex); |
960 OWF_Mutex_Lock(&context->sceneMutex); |
1142 |
961 |
1143 WFC_Context_CheckFastpath(context); |
962 scene = context->committedScene; |
1144 if (OWF_DisplayContext_FastpathEnabled(context->displayContext)) |
963 OWF_ASSERT(scene); |
1145 { |
964 |
1146 WFCboolean targetStreamAccessed; |
965 for (node = scene->elements; NULL != node; node = node->next) |
1147 OWFboolean screenRotation; |
966 { |
1148 screenRotation = OWF_Screen_Rotation_Supported(context->displayContext); |
967 |
1149 if (WFC_Context_Active(context)) |
968 WFC_ELEMENT* element = NULL; |
1150 { //Full fastpath is only supported for autonomous composition |
969 WFC_ELEMENT_STATE* elementState = NULL; |
1151 OWFNativeStreamType stream = OWF_INVALID_HANDLE; |
970 element = ELEMENT(node->data); |
1152 OWF_ROTATION rotation = OWF_ROTATION_0; |
971 |
1153 |
972 if (element->skipCompose) |
1154 DPRINT(("== WFC_Context_DoCompose(context = %p) - Fastpathing", context)); |
973 { |
1155 |
974 /* this element is somehow degraded, its source is missing or |
1156 stream = OWF_DisplayContext_FastpathStream(context->displayContext); |
975 * something else; skip to next element */ |
1157 if (screenRotation) |
976 DPRINT((" *** Skipping element %d", element->handle)); |
1158 { |
977 continue; |
1159 switch (context->rotation) |
978 } |
1160 { |
979 |
1161 case WFC_ROTATION_0: |
980 DPRINT((" Composing element %d", element->handle)); |
1162 { |
981 |
1163 rotation = OWF_ROTATION_0; |
982 /* BeginComposition may fail e.g. if the element's destination |
1164 break; |
983 * rectangle is something bizarre, i.e. causes overflows or |
1165 } |
984 * something. |
1166 case WFC_ROTATION_90: |
985 */ |
1167 { |
986 if ((elementState=WFC_Pipeline_BeginComposition(context, element))!=NULL) |
1168 rotation = OWF_ROTATION_90; |
987 { |
1169 break; |
988 owfSymElementNotifications(context, element); |
1170 } |
|
1171 case WFC_ROTATION_180: |
|
1172 { |
|
1173 rotation = OWF_ROTATION_180; |
|
1174 break; |
|
1175 } |
|
1176 case WFC_ROTATION_270: |
|
1177 { |
|
1178 rotation = OWF_ROTATION_270; |
|
1179 break; |
|
1180 } |
|
1181 default: |
|
1182 { |
|
1183 OWF_ASSERT(0); |
|
1184 rotation = OWF_ROTATION_0; |
|
1185 } |
|
1186 } |
|
1187 } |
|
1188 |
|
1189 if (!OWF_Screen_Post_Topmost_Layer(context->displayContext, stream, rotation)) |
|
1190 { |
|
1191 |
989 |
1192 DPRINT(("WFC_Context_Compose calls OWF_DisplayContext_DisableFastpath because !OWF_Screen_Post_Topmost_Layer()")); |
990 WFC_Pipeline_ExecuteSourceConversionStage(context, elementState); |
1193 OWF_DisplayContext_DisableFastpath(context->displayContext); |
991 WFC_Pipeline_ExecuteCropStage(context, elementState); |
1194 //If fastpath is disabled here then we need to compose properly this cycle |
992 WFC_Pipeline_ExecuteFlipStage(context, elementState); |
1195 } |
993 WFC_Pipeline_ExecuteRotationStage(context, elementState); |
1196 } |
994 WFC_Pipeline_ExecuteScalingStage(context, elementState); |
1197 targetStreamAccessed = OWF_DisplayContext_InternalStreamAccessed(context->displayContext); |
995 WFC_Pipeline_ExecuteBlendingStage(context, elementState); |
1198 if (OWF_DisplayContext_FastpathEnabled(context->displayContext) && ( targetStreamAccessed || !WFC_Context_Active(context) )) |
|
1199 { //Fastpath in non-autonomous composition just does a simple copy and post. |
|
1200 DPRINT(("== WFC_Context_DoCompose(context = %p) - fastpath copy target", context)); |
|
1201 if (WFC_Context_LockTargetForWriting(context)) |
|
1202 { |
|
1203 OWFboolean copy; |
|
1204 if (screenRotation) |
|
1205 { |
|
1206 if (WFC_ROTATION_90 == context->rotation || WFC_ROTATION_270 == context->rotation) |
|
1207 { |
|
1208 owfSetStreamFlipState(context->stream, OWF_TRUE); |
|
1209 } |
|
1210 else |
|
1211 { |
|
1212 owfSetStreamFlipState(context->stream, OWF_FALSE); |
|
1213 } |
|
1214 } |
|
1215 copy=OWF_DisplayContext_CopyFastpathedStreamToTargetStream(context); |
|
1216 if (!WFC_Context_Active(context)) |
|
1217 { |
|
1218 if (!copy) |
|
1219 { |
|
1220 DPRINT(("WFC_Context_Compose calls OWF_DisplayContext_DisableFastpath because !OWF_DisplayContext_CopyFastpathedStreamToTargetStream()")); |
|
1221 OWF_DisplayContext_DisableFastpath(context->displayContext); |
|
1222 //If fastpath is disabled here then we need to compose properly this cycle |
|
1223 } |
|
1224 } |
|
1225 else |
|
1226 { |
|
1227 copy=OWF_FALSE; |
|
1228 } |
|
1229 |
|
1230 WFC_Context_UnlockTarget(context,copy); |
|
1231 } |
|
1232 else |
|
1233 { |
|
1234 //If non-autonomous, then the lock target is required. |
|
1235 OWF_ASSERT(WFC_Context_Active(context)); |
|
1236 } |
|
1237 |
|
1238 } |
|
1239 if (OWF_DisplayContext_FastpathEnabled(context->displayContext)) |
|
1240 { |
|
1241 WFC_ELEMENT* topmostElement = NULL; |
|
1242 topmostElement = WFC_Scene_TopMostElement(context->committedScene); |
|
1243 owfSymElementNotifications(context, topmostElement); |
|
1244 } |
|
1245 } |
|
1246 if (!OWF_DisplayContext_FastpathEnabled(context->displayContext)) |
|
1247 { |
|
1248 DPRINT(("== WFC_Context_DoCompose(context = %p) - Composing", context)); |
|
1249 WFC_Context_PrepareComposition(context); |
|
1250 |
|
1251 scene = context->committedScene; |
|
1252 OWF_ASSERT(scene); |
|
1253 |
|
1254 for (node = scene->elements; NULL != node; node = node->next) |
|
1255 { |
|
1256 |
|
1257 WFC_ELEMENT* element = NULL; |
|
1258 WFC_ELEMENT_STATE* elementState = NULL; |
|
1259 element = ELEMENT(node->data); |
|
1260 |
|
1261 if (element->skipCompose) |
|
1262 { |
|
1263 /* this element is somehow degraded, its source is missing or |
|
1264 * something else; skip to next element */ |
|
1265 DPRINT((" *** Skipping element %d", element->handle)); |
|
1266 continue; |
|
1267 } |
|
1268 |
|
1269 DPRINT((" Composing element %d", element->handle)); |
|
1270 |
|
1271 /* BeginComposition may fail e.g. if the element's destination |
|
1272 * rectangle is something bizarre, i.e. causes overflows or |
|
1273 * something. |
|
1274 */ |
|
1275 if ((elementState=WFC_Pipeline_BeginComposition(context, element))!=NULL) |
|
1276 { |
|
1277 owfSymElementNotifications(context, element); |
|
1278 |
996 |
1279 WFC_Pipeline_ExecuteSourceConversionStage(context, elementState); |
997 WFC_Pipeline_EndComposition(context, element,elementState); |
1280 WFC_Pipeline_ExecuteCropStage(context, elementState); |
998 } |
1281 WFC_Pipeline_ExecuteFlipStage(context, elementState); |
999 } |
1282 WFC_Pipeline_ExecuteRotationStage(context, elementState); |
1000 |
1283 WFC_Pipeline_ExecuteScalingStage(context, elementState); |
1001 WFC_Context_FinishComposition(context); |
1284 WFC_Pipeline_ExecuteBlendingStage(context, elementState); |
1002 |
1285 |
|
1286 WFC_Pipeline_EndComposition(context, element,elementState); |
|
1287 } |
|
1288 } |
|
1289 |
|
1290 WFC_Context_FinishComposition(context); |
|
1291 DPRINT(("=== WFC_Context_DoCompose(context = %p) - Diplayed Composition", context)); |
|
1292 } |
|
1293 |
|
1294 WFC_Scene_UnlockSourcesAndMasks(context->committedScene); |
|
1295 owfSymProcessAllNotifications(context); |
1003 owfSymProcessAllNotifications(context); |
1296 OWF_Mutex_Unlock(&context->sceneMutex); |
1004 OWF_Mutex_Unlock(&context->sceneMutex); |
1297 |
1005 |
1298 OWF_Semaphore_Post(&context->compositionSemaphore); |
1006 OWF_Semaphore_Post(&context->compositionSemaphore); |
1299 } |
1007 } |
2009 } |
1697 } |
2010 |
1698 |
2011 /*--------------------------------------------------------------------------- |
1699 /*--------------------------------------------------------------------------- |
2012 * |
1700 * |
2013 *----------------------------------------------------------------------------*/ |
1701 *----------------------------------------------------------------------------*/ |
|
1702 |
|
1703 OWF_API_CALL void |
|
1704 WFC_Context_SourceStreamUpdated(OWFNativeStreamType stream, |
|
1705 OWFint event, |
|
1706 void* data, |
|
1707 void* returnParam) |
|
1708 { |
|
1709 (void)returnParam; |
|
1710 OWF_ASSERT(data); |
|
1711 |
|
1712 DPRINT(("WFC_Context_SourceStreamUpdated(%p, %x, %p)", |
|
1713 stream, event, data)); |
|
1714 stream = stream; /* suppress compiler warning */ |
|
1715 |
|
1716 switch (event) |
|
1717 { |
|
1718 case OWF_OBSERVER_RETURN_DEFAULT_EVENT: |
|
1719 if (returnParam) |
|
1720 { |
|
1721 OWF_DEFAULT_EVENT_PARAM* parameter = (OWF_DEFAULT_EVENT_PARAM*) returnParam; |
|
1722 if ((parameter->length) == sizeof(OWF_DEFAULT_EVENT_PARAM)) |
|
1723 { |
|
1724 parameter->event = OWF_STREAM_UPDATED; |
|
1725 } |
|
1726 } |
|
1727 break; |
|
1728 |
|
1729 case OWF_STREAM_UPDATED: |
|
1730 { |
|
1731 WFC_CONTEXT* context = NULL; |
|
1732 context = CONTEXT(data); |
|
1733 OWF_ASSERT(context); |
|
1734 OWF_Mutex_Lock(&context->updateFlagMutex); |
|
1735 |
|
1736 if (WFC_Context_Active(context)) |
|
1737 { |
|
1738 ++context->sourceUpdateCount; |
|
1739 } |
|
1740 OWF_Mutex_Unlock(&context->updateFlagMutex); |
|
1741 } |
|
1742 break; |
|
1743 default: |
|
1744 break; |
|
1745 } |
|
1746 } |
|
1747 |
|
1748 /*--------------------------------------------------------------------------- |
|
1749 * |
|
1750 *----------------------------------------------------------------------------*/ |
2014 OWF_API_CALL WFCboolean |
1751 OWF_API_CALL WFCboolean |
2015 WFC_Context_Active(WFC_CONTEXT* context) |
1752 WFC_Context_Active(WFC_CONTEXT* context) |
2016 { |
1753 { |
2017 OWF_ASSERT(context); |
1754 OWF_ASSERT(context); |
2018 |
1755 |