diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/coretoolkit/src/huicanvaswspainter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/coretoolkit/src/huicanvaswspainter.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,2646 @@ +/* +* Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Definition of CHuiCanvasWsPainter. +* +*/ + + + +#include "huicanvaswspainter.h" + +#include "uiacceltk/HuiCanvasVisual.h" +#include "HuiRenderPlugin.h" +#include "uiacceltk/HuiGc.h" +#include "uiacceltk/HuiPanic.h" +#include "uiacceltk/HuiUtil.h" +#include "uiacceltk/HuiStatic.h" +#include "uiacceltk/HuiEnv.h" +#include "uiacceltk/HuiControl.h" +#include "uiacceltk/HuiVisual.h" +#include "uiacceltk/HuiTextMesh.h" +#include "uiacceltk/HuiCanvasCmdBufferReader.h" +#include "huicanvasgc.h" +#include "huicanvaswsgc.h" +#include "HuiRenderSurface.h" +#include "huicanvastexturecache.h" +#include "huicanvasbackground.h" +#include "huicanvaswsswgc.h" +#include "huicanvasdebugwsgc.h" +#include "huicanvaswsbitgc.h" +#include "../../CommonInc/huiwscanvascommands.h" +#include + +#ifdef HUI_DEBUG_TRACK_DRAWING +#include "alfloggingconfiguration.h" +#include "alfcommanddebug.h" +#endif +#include +#include +#include + +#include "HuiCmdBufferBrush.h" + +/** + * Constants to define enabling/disabling render buffer automatically + * incase there are frequently new buffers posted. + * + * This may improve performance in some HW platforms. + * + */ +const TBool KHuiCanvasAutomaticRenderBufferUsage = EFalse; // Disbaled until all UI isses has been solved +const TInt KHuiCanvasDisableRenderBufferHandleInterval = 100; // Milliseconds +const TInt KHuiCanvasEnableRenderBufferHandleInterval = 500; // Milliseconds + +/** Internal constant to identify complex command buffers */ +const TInt KPossiblePerformanceProblemInWindow = 64; + + +/** ETrue - use SelectGcL to select gc implementation, + EFalse - use KHuiDefaultCanvasWsGc. */ +const TBool KHuiUseSelectGc = ETrue; + +/** Change this to select default rendering ws gc implementation. + Only used when KHuiUseSelectGc does not hold. */ +const THuiCanvasWsGcType KHuiDefaultCanvasWsGc = EHuiCanvasWsHw; + +//#define HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + +CHuiCanvasWsPainter* CHuiCanvasWsPainter::NewL() + { + CHuiCanvasWsPainter* self = new ( ELeave ) CHuiCanvasWsPainter; + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + + +CHuiCanvasWsPainter::CHuiCanvasWsPainter() + { + } + +void CHuiCanvasWsPainter::ConstructL() + { + CHuiStatic::Env().AddMemoryLevelObserver(this); + iWsCommandBufferReader = NULL; + iPartialCommandBuffer = NULL; + iCacheCleared = EFalse; + + if ( KHuiUseSelectGc ) + { + SelectGcL(); + } + else if (KHuiDefaultCanvasWsGc == EHuiCanvasWsHw) + { + iCanvasWsHwGc = CHuiCanvasWsHwGc::NewL(); + iCanvasWsGc = iCanvasWsHwGc; + } + else if (KHuiDefaultCanvasWsGc == EHuiCanvasWsSw) + { + iCanvasWsSwGc = CHuiCanvasWsSwGc::NewL(); + iCanvasWsGc = iCanvasWsSwGc; + } + else if (KHuiDefaultCanvasWsGc == EHuiCanvasWsBit) + { + iCanvasWsBitGc = CHuiCanvasWsBitGc::NewL(); + iCanvasWsGc = iCanvasWsBitGc; + } + else + { + // Never happens, right. + } + + iWsCommandBufferReader = new (ELeave) CHuiCanvasCmdBufferReader(); +#ifdef HUI_DEBUG_TRACK_DRAWING + iCommandDebugger = CAlfCommandDebug::NewL(); + CHuiCanvasWsGc* realGc = iCanvasWsGc; + iCanvasWsGc = CHuiCanvasDebugWsGc::NewL( realGc, *iCommandDebugger ); + +#endif + } + + +CHuiCanvasWsPainter::~CHuiCanvasWsPainter() + { + if (iCanvasVisual) + { + iCanvasVisual->Env().CanvasTextureCache().ReleaseAllCachedEntries(*iCanvasVisual); + iCanvasVisual->Env().RemoveMemoryLevelObserver(this); + } + else + { + CHuiStatic::Env().RemoveMemoryLevelObserver(this); + } + + ClearCommandSet(); + delete iWsCommandBufferReader; + delete iCanvasWsHwGc; + delete iCanvasWsSwGc; + delete iCanvasWsBitGc; + + iTempRegion.Close(); + iTempCurrentSubRegion.Close(); + iTempIntersectingRegion.Close(); +#ifdef HUI_DEBUG_TRACK_DRAWING + delete iCommandDebugger; +#endif + iFullUpdateRegion.Close(); + iShapeRegion.Close(); + } + + +CHuiGc::TOrientation CHuiCanvasWsPainter::CalculateRelativeOrientation() + { + // Calculate drawing command rotation as relative to the current display rotation. + // It may be that drawing commands has been sent when display was in different rotation. + TInt last = iCommandBuffers.Count() - 1; + CHuiGc::TOrientation relativeOrientation = CHuiGc::EOrientationNormal; + CHuiGc::TOrientation displayOrientation = CHuiStatic::Env().PrimaryDisplay().Orientation(); + CHuiGc::TOrientation drawingCommandOrientation = iCommandBuffers[last]->iOrientation; + + TInt rotationAngle[] = + { + 0, + 270, + 90, + 180 + }; + + TInt displayOrientationAngle = rotationAngle[displayOrientation]; + TInt drawingCommandOrientationAngle = rotationAngle[drawingCommandOrientation]; + TInt relativeOrientationAngle = drawingCommandOrientationAngle - displayOrientationAngle; + + // Check over/underflow + if (relativeOrientationAngle > 360) + { + relativeOrientationAngle -= 360; + } + else if (relativeOrientationAngle < 0) + { + relativeOrientationAngle += 360; + } + + switch (relativeOrientationAngle) + { + case 0: + { + relativeOrientation = CHuiGc::EOrientationNormal; + break; + } + case 90: + { + relativeOrientation = CHuiGc::EOrientationCW90; + break; + } + case 270: + { + relativeOrientation = CHuiGc::EOrientationCCW90; + break; + } + case 180: + { + relativeOrientation = CHuiGc::EOrientation180; + break; + } + default: + { + // As usual, this should not happen...but just in case it does use normal rotation + relativeOrientation = CHuiGc::EOrientationNormal; + break; + } + } + return relativeOrientation; + } + +void CHuiCanvasWsPainter::HandleBufferL(TRect& aDisplayRect, TInt aAction, const CHuiCanvasVisual& aUser, CHuiGc* aGc, TPoint aPos ) + { + #ifdef __ALF_SYMBIAN_RWINDOW_CLEARING_BUG_WORKAROUND__ + iTestFullDisplayRect = aDisplayRect; + #endif + + // Store user so that we can clear cache later + iCanvasVisual = (CHuiCanvasVisual*)&aUser; + + // Let canvas know about user and gc + CHuiCanvasGc& canvasGc = iCanvasWsGc->CanvasGc(); + canvasGc.SetVisual(aUser); + if (aGc) + { + canvasGc.SetGc(*aGc); + } + + if (iCommandBuffers.Count() != 0) + { +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL this = %i, Action = %i"), this, aAction ); + TTime startTime; + startTime.UniversalTime(); +#endif + + // Initialize canvas + canvasGc.SetDefaults(); + + // Make sure we got up to date update reagion + iFullUpdateRegion.Clear(); + TInt bufferCount = iCommandBuffers.Count(); + for (TInt cb = 0; cb < bufferCount; cb++) + { + iFullUpdateRegion.Union(iCommandBuffers[cb]->iUpdateRegion); + } + iFullUpdateRegion.Tidy(); + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + const TRect updateRegionBoundingRect = iFullUpdateRegion.BoundingRect(); + RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL iFullUpdateRegion.BoundingRect() = (%i,%i) (%i,%i)"), + updateRegionBoundingRect.iTl.iX, + updateRegionBoundingRect.iTl.iY, + updateRegionBoundingRect.iBr.iX, + updateRegionBoundingRect.iBr.iY + ); + + if (iCanvasWsGc->Type() == EHuiCanvasWsSw) + { + RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL - SW mode is used.")); + } + else if (iCanvasWsGc->Type() == EHuiCanvasWsBit) + { + RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL - BITGC mode is used.")); + } + + if (aUser.Effect()) + { + RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL - visual has EFFECT")); + } + + +#endif + + if (aAction == EDrawBuffer) + { + /* Check and enable render buffer if needed */ + EnableRenderBufferIfNeeded(ETrue); + + // Compenstate possible orientation mismatch between drawing commands and display orientation + // by letting iCanvasWsGc know about it. Mismatch usually happens when screen is rotated and + // it may cause visually unpleasent things at the screen. + CHuiGc::TOrientation relativeOrientation = CalculateRelativeOrientation(); + iCanvasWsGc->SetRelativeOrientation(relativeOrientation); + #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL - relativeOrientation = %i "), relativeOrientation); + #endif + + /* If window shape region has been changed, we should clear the window to get rid of old content. + * We also set all command buffers to "not drawn" state so that everything will be redrawn. + */ + TBool isFullUpdateRegionCleared = EFalse; + if(iShapeRegionClearingPending) + { + #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL - Clearing fullupdateregion")); + #endif + // Clear the window update region area + TBool doClear = ETrue; + iCanvasWsGc->EnableUpdateRegion(iFullUpdateRegion, doClear); + iCanvasWsGc->DisableUpdateRegion(); + isFullUpdateRegionCleared = ETrue; + + // Cause a full redraw for the canvas visual + SetAllBuffersChanged(ETrue); + ClearAllBufferStatusFlags(EHuiCanvasBufferStatusDrawn); + iShapeRegionClearingPending = EFalse; + } + + + /* Check if we have buffers that are not yet been drawn (or we render buffer is disabled) */ + TBool cachePrepared = !HasCommandBuffersWithoutFlags(EHuiCanvasBufferStatusDrawn) || !iCanvasWsGc->IsRenderBufferEnabled(); + + /* Begin draw. If render buffer is used this sets up the render buffer if needed */ + iCanvasWsGc->BeginActionL(aAction,aDisplayRect,aUser,cachePrepared,iFullUpdateRegion); + + #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + if (iCanvasWsGc->IsRenderBufferEnabled()) + { + RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL renderbuffer is ENABLED")); + } + else + { + RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL renderbuffer is DISABLED")); + } + #endif + + /* We do not ignore unchanged buffers currently */ + TBool ignoreUnChangedBuffers = EFalse; + + /* We can ignore buffers that only update areas which get clipped */ + TBool ignoreClippedBuffers = ETrue; + if (relativeOrientation != CHuiGc::EOrientationNormal) + { + ignoreClippedBuffers = EFalse; + } + + /* We can ignore buffers that has previously already been drawn into render buffer */ + TBool ignoreHandledBuffers = iCanvasWsGc->IsRenderBufferEnabled() && iCanvasWsGc->IsRenderBufferInitialized(); + + + /* + * We need to clear area if render buffer is used because otherwise it will cause dimming for semitransparent areas. + * + * NOTE1: We do not clear if the window is opaque. This is a bit questionable, but Avkon seems to rely + * quite much on luck with its drawing and there are areas in the windows which are not always covered + * by drawing commands, thus random garabage from previous frames would be visible if such window + * update area would always be cleared. + * + * NOTE2: We handle window that has background clearing enabled similarly as transparent window + * because their wanted behaviour is similar to transparent window (user wants to see the stuff + * behind window drawing commands and may want to draw commands translucently). + * + * -> So always clear if drawing vie render buffer and window is transparent or has backround. + * + */ + TBool clearBeforeHandlingBuffer = iCanvasWsGc->IsRenderBufferEnabled() + && (!(aUser.Flags() & EHuiVisualFlagOpaqueHint) || aUser.IsBackgroundDrawingEnabled()) + && !isFullUpdateRegionCleared; + + // TODO: Should avoid trap, but EndActionL must always be called + TRAPD(err, DoHandleAllBuffersL( aDisplayRect, aAction, aUser, aGc, aPos, + ignoreUnChangedBuffers, + ignoreClippedBuffers, + ignoreHandledBuffers, + clearBeforeHandlingBuffer)); + + if (err != KErrNone) + { + RDebug::Print(_L("CHuiCanvasWsPainter::HandleBufferL(): draw error = %i "), err); + RenewAllBuffers(); + } + + // Workaround for fact that WSERV sends command buffers that do not contain real drawing commands. + // If there are no real drawing commnads, just avoid display update at the EndAction so that + // we don't write empty pixels to screen and cause flicker. + TBool updateDisplay = HasCommandBuffers(EHuiCanvasBufferContainsDrawing); + + /* End draw. If render buffer is in use, this will update the screen */ + iCanvasWsGc->EndActionL(iFullUpdateRegion, updateDisplay); + + /* Mark that cache is not more clear */ + iCacheCleared = EFalse; + } + else if (aAction == EScanBuffer) + { + /* Check and enable render buffer if needed */ + EnableRenderBufferIfNeeded(ETrue); + + /* Check if we have buffers that are not yet prepared (or we render buffer is disabled) */ + TBool cachePrepared = !HasCommandBuffersWithoutFlags(EHuiCanvasBufferStatusScanned) || !iCanvasWsGc->IsRenderBufferEnabled(); + + /* Begin scan. If render buffer is used this sets up the render buffer if needed */ + iCanvasWsGc->BeginActionL(aAction,aDisplayRect,aUser,cachePrepared,iFullUpdateRegion); + + #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + if (iCanvasWsGc->IsRenderBufferEnabled()) + { + RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL renderbuffer is ENABLED")); + } + else + { + RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL renderbuffer is DISABLED")); + } + #endif + + /* We do not ignore unchanged buffers currently */ + TBool ignoreUnChangedBuffers = EFalse; + + /* We do not ignore clipped buffers as they possibly contain items that may soon appear on the screen */ + TBool ignoreClippedBuffers = EFalse; + + /* We can ignore buffers that has previously already been scanned */ + TBool ignoreHandledBuffers = ETrue; + + /* No need to clear area if scanning */ + TBool clearBeforeHandlingBuffer = EFalse; + + // TODO: Should avoid trap, but EndActionL must always be called + TRAPD(err, DoHandleAllBuffersL( aDisplayRect, aAction, aUser, aGc, aPos, + ignoreUnChangedBuffers, + ignoreClippedBuffers, + ignoreHandledBuffers, + clearBeforeHandlingBuffer)); + + if (err != KErrNone) + { + RDebug::Print(_L("CHuiCanvasWsPainter::HandleBufferL(): scan error = %i "), err); + RenewAllBuffers(); + } + + /* End draw. If render buffer is in use, this will update the screen */ + iCanvasWsGc->EndActionL(iFullUpdateRegion, EFalse); + + /* Mark that cache is not more clear */ + iCacheCleared = EFalse; + + /* Update dirty area to aDisplayRect in case this action is originated from dirty area scan */ + aDisplayRect = DirtyRect(); + } + + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + TTime endTime; + endTime.UniversalTime(); + TInt timeInMs = endTime.MicroSecondsFrom( startTime ).Int64()/1000; + RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL took %i ms"), timeInMs); +#endif + } + + } + +void CHuiCanvasWsPainter::DoHandleAllBuffersL( TRect& aDisplayRect, + TInt aAction, + const CHuiCanvasVisual& aUser, + CHuiGc* aGc, + TPoint& aPos, + TBool aIgnoreUnChangedBuffers, + TBool aIgnoreClippedBuffers, + TBool aIgnoreHandledBuffers, + TBool aClearBeforeHandlingBuffers) + { + UpdateBufferUpdateRegions(aPos); + + TInt bufferCount = iCommandBuffers.Count(); + for (TInt cb = 0; cb < bufferCount; cb++) + { + CHuiCanvasCommandBuffer* cmdbuffer = iCommandBuffers[cb]; + + #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL Buffer size: %i "), iCommandBuffers[cb]->iCommands->Size()); + for (TInt k=0; k < cmdbuffer->iUpdateRegion.Count();k++) + { + RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL Buffer region rect: %i,%i, %i,%i "), + cmdbuffer->iUpdateRegion[k].iTl.iX, + cmdbuffer->iUpdateRegion[k].iTl.iY, + cmdbuffer->iUpdateRegion[k].iBr.iX, + cmdbuffer->iUpdateRegion[k].iBr.iY); + } + #endif + + if (aIgnoreUnChangedBuffers && !cmdbuffer->iChanged) + { + #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL Skipping buffer, it has not changed")); + #endif + continue; + } + + if (aIgnoreHandledBuffers) + { + if (aAction == EDrawBuffer && (cmdbuffer->iStatusFlags & EHuiCanvasBufferStatusDrawn)) + { + #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL Skipping buffer, it has already been drawn.")); + #endif + continue; + } + else if (aAction == EScanBuffer && (cmdbuffer->iStatusFlags & EHuiCanvasBufferStatusScanned)) + { + #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL Skipping buffer, it has already been scanned.")); + #endif + continue; + } + else + { + // No, we dont ignore. + } + } + + if (aIgnoreClippedBuffers && IsBufferCompletelyOutisideClippingRegion(*cmdbuffer)) + { + #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL: Skipping buffer %i, as it is completely clipped"), cb); + #endif + continue; + } + + if (aGc) + { + #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL ClipRegion before clipping to updateregion:")); + const TRegion& originalclipregion = aGc->ClipRegion(); + for (TInt k=0; k < originalclipregion.Count();k++) + { + + RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL original clip region rect: %i,%i, %i,%i "), + originalclipregion[k].iTl.iX, + originalclipregion[k].iTl.iY, + originalclipregion[k].iBr.iX, + originalclipregion[k].iBr.iY); + } + #endif + + + // If buffers has been scanned, but it does not seem to contain any real drawing commands we discard it + if (!(cmdbuffer->iStatusFlags & EHuiCanvasBufferContainsDrawing) && (cmdbuffer->iStatusFlags & EHuiCanvasBufferStatusScanned)) + { + #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L("CHuiCanvasWsPainter::DoHandleAllBuffersL: Hmmm, WSERV has sent buffer without real drawing commands."), cb); + #endif + continue; + } + + // Clip drawing to update area. This seems to improve performance although + // it may depend on used HW. + iCanvasWsGc->EnableUpdateRegion(iCommandBuffers[cb]->iUpdateRegion, aClearBeforeHandlingBuffers); + + #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL ClipRegion after clipping to updateregion:")); + const TRegion& clipregion = aGc->ClipRegion(); + for (TInt k=0; k < originalclipregion.Count();k++) + { + + RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL current clip region rect: %i,%i, %i,%i "), + clipregion[k].iTl.iX, + clipregion[k].iTl.iY, + clipregion[k].iBr.iX, + clipregion[k].iBr.iY); + } + #endif + + TRAPD(error, DoHandleBufferL(cb, aDisplayRect, aAction, aUser, aGc, aPos )); + + if (error) + { + #ifdef _DEBUG + RDebug::Print(_L("CHuiCanvasWsPainter::DoHandleAllBuffersL: Error in buffer %i, continuing."), cb); + #endif + } + + iCanvasWsGc->DisableUpdateRegion(); + } + else + { + DoHandleBufferL(cb, aDisplayRect, aAction, aUser, aGc, aPos); + } + + // Update buffer status + if (aAction == EDrawBuffer) + { + cmdbuffer->SetStatusFlags(EHuiCanvasBufferStatusDrawn); + } + else if (aAction == EScanBuffer) + { + cmdbuffer->SetStatusFlags(EHuiCanvasBufferStatusScanned); + } + else + { + // This should not happen + } + } + } + + +void CHuiCanvasWsPainter::HandleBufferL(TRect& aDisplayRect, TInt aAction, const CHuiCanvasVisual& aUser, CHuiGc* aGc, TPoint aPos, TPtrC8 aCommands, CHuiCanvasCommandBuffer * /*buf*/) + { + TUint8 *ptr = const_cast(aCommands.Ptr()); + TInt length = aCommands.Length(); + TPtr8 cmds(ptr, length, length); + CHuiCanvasCommandBuffer *buf = new (ELeave)CHuiCanvasCommandBuffer; + CleanupStack::PushL(buf); + buf->iUpdateRegion.AddRect(aDisplayRect); + if (iCanvasVisual && iCanvasVisual->Display()) + { + buf->iOrientation = iCanvasVisual->Display()->Orientation(); + } + DoHandleBufferStringL(-1, aDisplayRect, aAction, aUser, aGc, aPos, cmds, buf); + CleanupStack::PopAndDestroy(); + } + +void CHuiCanvasWsPainter::DoPeekBufferL(TInt aIndex) + { + RMemReadStream& readerStream = iWsCommandBufferReader->Stream(); + CHuiCanvasCommandBuffer& commandBuffer = *iCommandBuffers[aIndex]; + HBufC8* cmdBuf = commandBuffer.iCommands; + TInt bufLength = cmdBuf->Length(); + + TPtr8 des = cmdBuf->Des(); + iWsCommandBufferReader->Init( des, bufLength ); + TInt offset = 0; + TInt command = 0; + TBool donePeeking = EFalse; + do + { + command = readerStream.ReadUint8L(); + + switch ( command ) + { + case EAlfFrameContainsUnsupportedCommands: + { + TUint8 containsUnsupportedCommands = iWsCommandBufferReader->Stream().ReadUint8L(); + if ( containsUnsupportedCommands ) + { + commandBuffer.iContainsUnsupportedCommands = ETrue; + } + break; + } + case EAlfFrameFlags: + { + TInt flags; + iWsCommandBufferReader->ReadInt32L( flags ); + if (flags & EAlfTransparentContent) + { + EnableRenderBuffer(ETrue); + } + break; + } + case EAlfSetUpdateRegion: + { + WsSetUpdateRegionL(aIndex); + commandBuffer.iPositionForUpdateRegion = Visual()->DisplayRect().iTl.Round(); + break; + } + case EAlfCommandIndexArrayHeader: + { + TInt tmp; + iWsCommandBufferReader->ReadInt8L(); // padding + iWsCommandBufferReader->ReadInt32L( tmp ); + iWsCommandBufferReader->ReadInt32L( tmp ); + break; + } + case EAlfPacketPadding: + { + DoDigestPaddingL(); + break; + } + case EAlfSetShapeRegion: + { + WsSetShapeRegionL( aIndex ); + break; + } + default: + { + donePeeking = ETrue; + break; + } + } + + offset = readerStream.Source()->TellL( MStreamBuf::ERead ).Offset(); + + } while( offset < bufLength && !donePeeking); + + iCommandBuffers[aIndex]->iOriginalDisplayRect = iCanvasVisual->DisplayRect(); + } + + +#ifdef HUI_DEBUG_TRACK_DRAWING +void CHuiCanvasWsPainter::DoHandleBufferL(TInt aIndex, TRect& aDisplayRect, TInt aAction, const CHuiCanvasVisual& aUser, CHuiGc* aGc, TPoint& aPos) +#else +void CHuiCanvasWsPainter::DoHandleBufferL(TInt aIndex, TRect& aDisplayRect, TInt aAction, const CHuiCanvasVisual& aUser, CHuiGc* aGc, TPoint& aPos) +#endif + { + CHuiCanvasCommandBuffer* commandBuffer = iCommandBuffers[aIndex]; + HBufC8* cmdBuf = commandBuffer->iCommands; + +#ifdef HUI_DEBUG_TRACK_DRAWING + if ( commandBuffer->iTrackedBuffer ) + { + RDebug::Print( _L("CHuiCanvasWsPainter::DoHandleBufferL - Tracked buffer found")); + switch ( aAction ) + { + case EDrawBuffer: + { + RDebug::Print( _L("CHuiCanvasWsPainter::DoHandleBufferL - draw buffer")); + break; + } + case EScanBuffer: + { + RDebug::Print( _L("CHuiCanvasWsPainter::DoHandleBufferL - scan buffer")); + break; + } + default:; + } + } + + iCommandDebugger->StartFrame(); + if ( commandBuffer->iProcessName ) + { + // UNCOMMENT THIS IF YOU WANT TO PRINT EVERYTHING + // iCommandDebugger->SetPrint( ETrue ); + // UNCOMMENT THIS IF YOU WANT PRINTS ONLY FOR CERTAIN PROCESS! + // DEFINE PROCESS NAME IN alfcommanddebug.cpp + // iCommandDebugger->SetPrint( iCommandDebugger->TrackProcess( commandBuffer->iProcessName ) ); + RDebug::Print(_L("CHuiCanvasWsPainter::DoHandleBufferL - Process [%S]"), commandBuffer->iProcessName ); + } + else + { +// RDebug::Print(_L("CHuiCanvasWsPainter::DoHandleBufferL - Process [already dead or not found]")); + } +#endif + + TPtr8 des = cmdBuf->Des(); + DoHandleBufferStringL(aIndex, aDisplayRect, aAction, aUser, aGc, aPos, des, commandBuffer); + } + +void CHuiCanvasWsPainter::DoHandleBufferStringL(TInt aIndex, TRect& /*aDisplayRect*/, TInt /*aAction*/, const CHuiCanvasVisual& /*aUser*/, CHuiGc* /*aGc*/, TPoint& aPos, TPtr8 aCmds, CHuiCanvasCommandBuffer *aCommandBuffer) + { + RMemReadStream& readerStream = iWsCommandBufferReader->Stream(); + TInt bufLength = aCmds.Length(); + TPtr8 des = aCmds; + CHuiCanvasCommandBuffer *commandBuffer = aCommandBuffer; + TPoint deltaPos = aPos - commandBuffer->iOriginalDisplayRect.iTl; + + iCanvasWsGc->SetPositionDelta( deltaPos ); + iWsCommandBufferReader->Init( des, bufLength ); + TInt offset = 0; + TInt command = 0; + do + { + command = readerStream.ReadUint8L(); +#ifdef HUI_DEBUG_TRACK_DRAWING + iCommandDebugger->SetDescription( command ); +#endif + + // Command cases are ordered approximately in the order so that most common ones are at first + switch ( command ) + { + case EAlfFrameContainsUnsupportedCommands: + { + TUint8 containsUnsupportedCommands = iWsCommandBufferReader->Stream().ReadUint8L(); + if (containsUnsupportedCommands ) + { + // RDebug::Print(_L("Unsupported commands in this frame")); + } + break; + } + case EAlfFrameFlags: + { + TInt flags; + iWsCommandBufferReader->ReadInt32L( flags ); + if ( flags != 0 ) + { + RDebug::Print(_L("FLAGS: %d"), flags ); + } + break; + } + case EAlfSetUpdateRegion: + { + WsSetUpdateRegionL(aIndex); + break; + } + case EAlfSetShapeRegion: + { + iTempRegion.Clear(); + iWsCommandBufferReader->ReadRegionL( iTempRegion ); + break; + } + case EAlfSetBrushStyle: + { + WsSetBrushStyleL(); + break; + } + case EAlfSetOrigin: + { + WsSetOriginL(); + break; + } + case EAlfSetPenStyle: + { + WsSetPenStyleL(); + break; + } + case EAlfSetClippingRegion: + { + WsSetClippingRegionL(); + break; + } + case EAlfResetClippingRegion: + { + WsResetClippingRegionL(); + break; + } + case EAlfSetBrushColor: + { + WsSetBrushColorL(); + break; + } + case EAlfBitBltMasked: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsBitBltMaskedL(); + break; + } + case EAlfCombinedBitBlitMasked: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsCombinedBitBlitMaskedL(); + break; + } + case EAlfReset: + { + WsResetL(); + break; + } + case EAlfSetPenColor: + { + WsSetPenColorL(); + break; + } + case EAlfBitBltRect: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsBitBltRectL(); + break; + } + case EAlfSetDrawMode: + { + WsSetDrawModeL(); + break; + } + case EAlfSetCharJustification: + { + WsSetCharJustificationL(); + break; + } + case EAlfDrawBitmapMasked: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawBitmapMaskedL(); + break; + } + case EAlfSetUnderlineStyle: + { + WsSetUnderlineStyleL(); + break; + } + case EAlfResetFont: + { + WsResetFontL(); + break; + } + case EAlfSetStrikethroughStyle: + { + WsSetStrikethroughStyleL(); + break; + } + case EAlfBitBlt: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsBitBltL(); + break; + } + case EAlfBitBltMaskedPoint: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsBitBltMaskedPointL(); + break; + } + case EAlfClear: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsClearL(); + break; + } + case EAlfClearRect: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsClearRectL(); + break; + } + case EAlfResetBrushPattern: + { + WsResetBrushPatternL(); + break; + } + case EAlfDrawText1: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawText1L(); + break; + } + case EAlfDrawText2: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawText2L(); + break; + } + case EAlfDrawText3: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawText3L(); + break; + } + case EAlfDrawText4: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawText4L(); + break; + } + case EAlfDrawText5: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawText5L(); + break; + } + case EAlfDrawArc: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawArcL(); + break; + } + case EAlfDrawPie: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawPieL(); + break; + } + case EAlfDrawBitmap1: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawBitmap1L(); + break; + } + case EAlfDrawBitmap2: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawBitmap2L(); + break; + } + case EAlfDrawBitmap3: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawBitmap3L(); + break; + } + case EAlfDrawRoundRect: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawRoundRectL(); + break; + } + case EAlfDrawPolyLine: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawPolyLineL(); + break; + } + case EAlfDrawPolyLineNoEndPoint: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawPolyLineNoEndPointL(); + break; + } + case EAlfDrawPolygon: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawPolygonL(); + break; + } + case EAlfDrawEllipse: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawEllipseL(); + break; + } + case EAlfDrawLine: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawLineL(); + break; + } + case EAlfDrawLineTo: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawLineToL(); + break; + } + case EAlfDrawLineBy: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawLineByL(); + break; + } + case EAlfDrawRect: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawRectL(); + break; + } + case EAlfDrawTextVertical1: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawTextVertical1L(); + break; + } + case EAlfDrawTextVertical2: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawTextVertical2L(); + break; + } + case EAlfDrawTextVertical3: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawTextVertical3L(); + break; + } + case EAlfDrawTextVertical4: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawTextVertical4L(); + break; + } + case EAlfDrawTextVertical5: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsDrawTextVertical5L(); + break; + } + case EAlfMoveTo: + { + WsMoveToL(); + break; + } + case EAlfMoveBy: + { + WsMoveByL(); + break; + } + case EAlfPlot: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsPlotL(); + break; + } + case EAlfSetBrushOrigin: + { + WsSetBrushOriginL(); + break; + } + case EAlfSetPenSize: + WsSetPenSizeL(); + break; + case EAlfSetTextShadowColor: + { + WsSetTextShadowColorL(); + break; + } + case EAlfSetWordJustification: + { + WsSetWordJustificationL(); + break; + } + case EAlfSetBrushPattern: + { + WsSetBrushPatternL(); + break; + } + case EAlfSetBrushPattern2: + { + WsSetBrushPatternL(); + break; + } + case EAlfSetFont: + { + WsSetFontL(); + break; + } + case EAlfContentTag: + { + WsContentTagL(); + break; + } + case EAlfCopyRect: + WsCopyRectL(); + break; + case EAlfUpdateJustification: + { + WsUpdateJustificationL(); + break; + } + case EAlfUpdateJustificationVertical: + { + WsUpdateJustificationVerticalL(); + break; + } + case EAlfSetFontNoDuplicate: + { + WsSetFontNoDuplicateL(); + break; + } + case EAlfHasBrushPattern: + case EAlfHasFont: + case EAlfBrushColor: + case EAlfPenColor: + case EAlfTextShadowColor: + { + // these values are cached on client side, we dont do anything. + break; + } + case EAlfCopySettings: + { + WsCopySettingsL(); + break; + } + case EAlfSetClippingRect: + { + WsSetClippingRectL(); + break; + } + case EAlfCancelClippingRect: + { + WsCancelClippingRectL(); + break; + } + case EAlfSetFaded: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsSetFadedL(); + } + break; + case EAlfSetFadingParameters: + { + WsSetFadingParametersL(); + break; + } + case EAlfFadeArea: + { + commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing); + WsFadeAreaL(); + break; + } + case EAlfMapColors: + // MapColors is not supported. Client should never supply this command. + User::Leave( KErrNotSupported ); + break; + case EAlfSetUserDisplayMode: + { + WsSetUserDisplayModeL(); + break; + } + case EAlfUseFont: + { + WsUseFontL(); + break; + } + case EAlfSendSyncDataBlock: + { + break; + } + case EAlfWindowInactivateWindow: + { + // Nothing to do + break; + } + case EAlfPacketPadding: + { + DoDigestPaddingL(); + break; + } + case EAlfCommandIndexArrayHeader: + { + TInt tmp; + iWsCommandBufferReader->ReadInt8L(); // padding + iWsCommandBufferReader->ReadInt32L( tmp ); + iWsCommandBufferReader->ReadInt32L( tmp ); + break; + } + case EAlfCommandIndexArray: + { + TUint8 a = iWsCommandBufferReader->ReadInt8L(); + iWsCommandBufferReader->ReadInt8L(); + iWsCommandBufferReader->ReadInt8L(); + TInt tmp; + TRect tmp2; + for(TUint8 i=0;iReadInt32L(tmp); + iWsCommandBufferReader->ReadInt32L(tmp); + iWsCommandBufferReader->ReadInt32L(tmp); + iWsCommandBufferReader->ReadRectL(tmp2); + } + break; + } + + + default: + { + // We should never ever get here + HUI_DEBUG1(_L("CHuiCanvasVisual::HandleWsBufferL. Error: Unknown command=%d"), command); + break; + } + }// end switch + offset = readerStream.Source()->TellL( MStreamBuf::ERead ).Offset(); + + } while( offset < bufLength ); +#ifdef HUI_DEBUG_TRACK_DRAWING + iCommandDebugger->EndFrame(); +#endif + } + + +void CHuiCanvasWsPainter::SetCommandSetL( const TDesC8& aCommands ) + { + CHuiCanvasPainter::SetCommandSetL(aCommands); + + TInt latest = iCommandBuffers.Count() - 1; + DoPeekBufferL(latest); + SelectGcL(); + + // If shape region has changed recalculate all update regions and remove redundant buffers + if (iShapeRegionClippingPending) + { + TInt bufferCount = iCommandBuffers.Count(); + for (TInt cb = 0; cb < bufferCount; cb++) + { + CHuiCanvasCommandBuffer* cmdbuffer = iCommandBuffers[cb]; + cmdbuffer->iUpdateRegion.Copy(cmdbuffer->iOriginalUpdateRegion); + cmdbuffer->iUpdateRegion.Intersect(iShapeRegion); + cmdbuffer->iUpdateRegion.Tidy(); + } + iShapeRegionClippingPending = EFalse; + RemoveRedundantBuffers(); + } + + // Release currently cached images. + // They may still be taken into use after next HandleBuffferL call. + if (iCanvasVisual) + { + iCanvasVisual->Env().CanvasTextureCache().ReleaseAllCachedEntries(*iCanvasVisual); + } + } + + +void CHuiCanvasWsPainter::ClearCommandSet() + { +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L(">> CHuiCanvasWsPainter::ClearCommandSet this = %i"), this ); + TTime startTime; + startTime.UniversalTime(); +#endif + + CHuiCanvasPainter::ClearCommandSet(); + // Release currently cached images. + // They may still be taken into use after next HandleBuffferL call. + if (iCanvasVisual) + { + iCanvasVisual->Env().CanvasTextureCache().ReleaseAllCachedEntries(*iCanvasVisual); + } + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + TTime endTime; + endTime.UniversalTime(); + TInt timeInMs = endTime.MicroSecondsFrom( startTime ).Int64()/1000; + RDebug::Print(_L(">> CHuiCanvasWsPainter::ClearCommandSet took %i ms"), timeInMs); +#endif + + } + +struct TArrayHeader + { + TInt32 iOffset; + TInt32 iSize; + }; + +void CHuiCanvasWsPainter::AddCommandSetL( const TDesC8& aMoreCommands ) + { +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L(">> CHuiCanvasWsPainter::AddCommandSetL this = %i"), this ); + TTime startTime; + startTime.UniversalTime(); +#endif + + CHuiCanvasPainter::AddCommandSetL(aMoreCommands); + TInt latest = iCommandBuffers.Count() - 1; + DoPeekBufferL(latest); + SelectGcL(); + + // If shape region has changed recalculate all update regions + if (iShapeRegionClippingPending) + { + TInt bufferCount = iCommandBuffers.Count(); + for (TInt cb = 0; cb < bufferCount; cb++) + { + CHuiCanvasCommandBuffer* cmdbuffer = iCommandBuffers[cb]; + cmdbuffer->iUpdateRegion.Copy(cmdbuffer->iOriginalUpdateRegion); + cmdbuffer->iUpdateRegion.Intersect(iShapeRegion); + cmdbuffer->iUpdateRegion.Tidy(); + } + iShapeRegionClippingPending = EFalse; + } + + RemoveRedundantBuffers(); + + // New command set may contain BitBlt commands + // and those cached images must be refreshed + if (iCanvasVisual) + { + // Release currently cached images. + // They may still be taken into use after next HandleBufferL call. + iCanvasVisual->Env().CanvasTextureCache().ReleaseAllCachedEntries(*iCanvasVisual); + } + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + TTime endTime; + endTime.UniversalTime(); + TInt timeInMs = endTime.MicroSecondsFrom( startTime ).Int64()/1000; + RDebug::Print(_L(">> CHuiCanvasWsPainter::AddCommandSetL took %i ms"), timeInMs); +#endif + +#ifdef HUI_ENABLE_SUBWINDOW_FX + TInt count = NumBuffers(); + if (!count) return; + const TDesC8 &more = At(count-1)->iCommands->Des(); + //RDebug::Print(_L("MoreCommands: %x : %d"), aMoreCommands.Ptr(), aMoreCommands.Length()); + TPtrC8 header = more.Mid(4, sizeof(TArrayHeader)); // the magic comes from CAlfRsSendBuffer::WriteFollowingFrameOffsetL. + TArrayHeader *ptr = (TArrayHeader*)header.Ptr(); + //RDebug::Print(_L("Ptr: %d : %d"), ptr->iOffset, ptr->iSize); + TPtrC8 indexTable = more.Mid(ptr->iOffset, ptr->iSize); + + if (iCanvasVisual->Brushes() && iCanvasVisual) + { + ParseCmdBufferL(*iCanvasVisual->Brushes(), more, indexTable, CanvasGc(), *CanvasWsGc(), *iCanvasVisual, *this); + } +#endif + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + TTime endTime2; + endTime2.UniversalTime(); + TInt time2InMs = endTime2.MicroSecondsFrom( startTime ).Int64()/1000; + RDebug::Print(_L(">> CHuiCanvasWsPainter::AddCommandSetL including brush creation took %i ms"), time2InMs); +#endif + + } + +void CHuiCanvasWsPainter::AddPartialCommandSetL( const TDesC8& aMoreCommands, TBool aLastPart ) + { + CHuiCanvasPainter::AddPartialCommandSetL(aMoreCommands,aLastPart); + } + +#ifdef HUI_DEBUG_TRACK_DRAWING +void CHuiCanvasWsPainter::SetTrackCommandSet( TFileName& aFileName, TBool aTrack ) + { + CHuiCanvasPainter::SetTrackCommandSet( aFileName, aTrack ); + } +#endif + +void CHuiCanvasWsPainter::ClearCache() + { + if (iCanvasVisual && !iCacheCleared) + { +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + RDebug::Print(_L(">> CHuiCanvasWsPainter::ClearCache this = %i"), this ); + TTime startTime; + startTime.UniversalTime(); +#endif + TRAP_IGNORE(SelectGcL()); + RenewAllBuffers(); + SetAllBuffersChanged(ETrue); + iCanvasWsGc->ClearCache(); + iCanvasVisual->Env().CanvasTextureCache().ReleaseAllCachedEntries(*iCanvasVisual); + iCacheCleared = ETrue; + +#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL + TTime endTime; + endTime.UniversalTime(); + TInt timeInMs = endTime.MicroSecondsFrom( startTime ).Int64()/1000; + RDebug::Print(_L(">> CHuiCanvasWsPainter::ClearCache took %i ms"), timeInMs); +#endif + + } + } + + +void CHuiCanvasWsPainter::WsBitBltL() + { + TPoint point(0,0); + TInt bitmapHandle = 0; + iWsCommandBufferReader->ReadPointL( point ); + iWsCommandBufferReader->ReadBitmapHandleL( bitmapHandle ); + iCanvasWsGc->WsBitBltL(bitmapHandle,point); + } + +void CHuiCanvasWsPainter::WsBitBltRectL() + { + iWsCommandBufferReader->ReadL( (TUint8*)&iStructBitBlitRect, sizeof( TStructBitBlitRect ) ); + iCanvasWsGc->WsBitBltRectL( + iStructBitBlitRect.iBitmapHandle, + iStructBitBlitRect.iPoint, + iStructBitBlitRect.iRect); + } + +void CHuiCanvasWsPainter::WsBitBltMaskedL() + { + iWsCommandBufferReader->ReadL( (TUint8*)&iStructBitBlitMasked, sizeof( TStructBitBlitMasked ) ); + iCanvasWsGc->WsBitBltMaskedL( + iStructBitBlitMasked.iBitmapHandle, + iStructBitBlitMasked.iMaskHandle, + iStructBitBlitMasked.iInvertMask, + iStructBitBlitMasked.iPoint, + iStructBitBlitMasked.iRect); + } + + +void CHuiCanvasWsPainter::WsCombinedBitBlitMaskedL() + { + TRect clipRect(0,0,0,0); + TRect blitRect(0,0,0,0); + TInt itemCount = iWsCommandBufferReader->ReadInt8L(); + iWsCommandBufferReader->ReadL( (TUint8*)&clipRect, sizeof( TRect ) ); + iWsCommandBufferReader->ReadL( (TUint8*)&blitRect, sizeof( TRect ) ); + + TInt index(0); + + RArray combinedBlitItems; + THuiCachedCombinedImageParams combinedBlitItem; + while( index++ < itemCount ) + { + iWsCommandBufferReader->ReadL( (TUint8*)&combinedBlitItem, sizeof( THuiCachedCombinedImageParams ) ); + combinedBlitItems.Append(combinedBlitItem); + } + // clipping rects were optimized away by renderstage. it must be set now. + // We use SetClippingRegion instead of SetClippingRect as they handle ws origin differently. + iTempRegion.Clear(); + iTempRegion.AddRect(clipRect); + iCanvasWsGc->WsSetClippingRegionL(iTempRegion); + iCanvasWsGc->WsCombinedBitBltMaskedL(blitRect, combinedBlitItems); + iCanvasWsGc->WsResetClippingRegionL(); + combinedBlitItems.Close(); + } + +void CHuiCanvasWsPainter::WsBitBltMaskedPointL() + { + TPoint point1(0,0); + TPoint point2(0,0); + TRect rect(0,0,0,0); + TInt bitmapHandle = 0; + TInt maskHandle = 0; + iWsCommandBufferReader->ReadPointL( point1 ); + iWsCommandBufferReader->ReadBitmapHandleL( bitmapHandle ); + iWsCommandBufferReader->ReadRectL( rect ); + iWsCommandBufferReader->ReadBitmapHandleL( maskHandle ); + iWsCommandBufferReader->ReadPointL( point2 ); + iCanvasWsGc->WsBitBltMaskedPointL(bitmapHandle,maskHandle,point1,point2,rect); + } + +void CHuiCanvasWsPainter::WsResetClippingRegionL() + { + iCanvasWsGc->WsResetClippingRegionL(); + } + +void CHuiCanvasWsPainter::WsClearL() + { + iCanvasWsGc->WsClearL(); + } + +void CHuiCanvasWsPainter::WsClearRectL() + { + TRect tmpRect1(0,0,0,0); + iWsCommandBufferReader->ReadRectL( tmpRect1 ); + iCanvasWsGc->WsClearRectL(tmpRect1); + } + +void CHuiCanvasWsPainter::WsResetBrushPatternL() + { + + } + +void CHuiCanvasWsPainter::WsResetFontL() + { + iCanvasWsGc->WsResetFontL(); + } + +void CHuiCanvasWsPainter::WsDrawArcL() + { + TPoint point1(0,0); + TPoint point2(0,0); + TRect rect(0,0,0,0); + iWsCommandBufferReader->ReadRectL( rect ); + iWsCommandBufferReader->ReadPointL( point1 ); + iWsCommandBufferReader->ReadPointL( point2 ); + iCanvasWsGc->WsDrawArcL(point1,point2,rect); + } + +void CHuiCanvasWsPainter::WsDrawPieL() + { + TPoint point1(0,0); + TPoint point2(0,0); + TRect rect(0,0,0,0); + iWsCommandBufferReader->ReadRectL( rect ); + iWsCommandBufferReader->ReadPointL( point1 ); + iWsCommandBufferReader->ReadPointL( point2 ); + iCanvasWsGc->WsDrawPieL(point1,point2,rect); + } + +void CHuiCanvasWsPainter::WsDrawBitmap1L() + { + TRect rect(0,0,0,0); + TInt bitmapHandle = 0; + iWsCommandBufferReader->ReadRectL( rect ); + iWsCommandBufferReader->ReadBitmapHandleL( bitmapHandle ); + iCanvasWsGc->WsDrawBitmap1L(bitmapHandle,rect); + } + +void CHuiCanvasWsPainter::WsDrawBitmap2L() + { + TRect rect1(0,0,0,0); + TRect rect2(0,0,0,0); + TInt bitmapHandle = 0; + iWsCommandBufferReader->ReadRectL( rect1); + iWsCommandBufferReader->ReadBitmapHandleL( bitmapHandle ); + iWsCommandBufferReader->ReadRectL( rect2); + iCanvasWsGc->WsDrawBitmap2L(bitmapHandle,rect1,rect2); + } + +void CHuiCanvasWsPainter::WsDrawBitmap3L() + { + TPoint point(0,0); + TInt bitmapHandle = 0; + iWsCommandBufferReader->ReadPointL( point ); + iWsCommandBufferReader->ReadBitmapHandleL( bitmapHandle ); + iCanvasWsGc->WsDrawBitmap3L(bitmapHandle,point); + } + +void CHuiCanvasWsPainter::WsDrawBitmapMaskedL() + { + iWsCommandBufferReader->ReadL( (TUint8*)&iStructDrawBitmapMasked, sizeof( TStructDrawBitmapMasked ) ); + iCanvasWsGc->WsDrawBitmapMaskedL( + iStructDrawBitmapMasked.iBitmapHandle, + iStructDrawBitmapMasked.iMaskHandle, + iStructDrawBitmapMasked.iInvertMask, + iStructDrawBitmapMasked.iRect1, + iStructDrawBitmapMasked.iRect2); + } + +void CHuiCanvasWsPainter::WsDrawRoundRectL() + { + TPoint point(0,0); + TRect rect(0,0,0,0); + iWsCommandBufferReader->ReadRectL( rect ); + iWsCommandBufferReader->ReadPointL( point ); + iCanvasWsGc->WsDrawRoundRectL(point,rect); + } + +void CHuiCanvasWsPainter::WsDrawPolyLineL() + { + CArrayFix* pointerArray = NULL; + iWsCommandBufferReader->ReadPointArrayL( pointerArray ); + iCanvasWsGc->WsDrawPolyLineL(pointerArray); + delete pointerArray; + } + +void CHuiCanvasWsPainter::WsDrawPolyLineNoEndPointL() + { + TPoint* pointerArray = NULL; + TInt count = 0; + iWsCommandBufferReader->ReadPointArrayL( pointerArray, count ); + iCanvasWsGc->WsDrawPolyLineNoEndPointL(pointerArray,count); + pointerArray = NULL; + } + +void CHuiCanvasWsPainter::WsDrawPolygonL() + { + CArrayFix* pointerArray; + TInt fillRule = 0; + iWsCommandBufferReader->ReadPointArrayL( pointerArray ); + iWsCommandBufferReader->ReadInt8L(); // command + iWsCommandBufferReader->ReadInt32L( fillRule ); + iCanvasWsGc->WsDrawPolygonL(pointerArray,fillRule); + delete pointerArray; + } + +void CHuiCanvasWsPainter::WsDrawEllipseL() + { + TRect rect(0,0,0,0); + iWsCommandBufferReader->ReadRectL( rect ); + iCanvasWsGc->WsDrawEllipseL(rect); + } + +void CHuiCanvasWsPainter::WsDrawLineL() + { + TPoint start(0,0); + TPoint end(0,0); + iWsCommandBufferReader->ReadPointL( start ); + iWsCommandBufferReader->ReadPointL( end ); + iCanvasWsGc->WsDrawLineL(start,end); + } + +void CHuiCanvasWsPainter::WsDrawLineToL() + { + TPoint point(0,0); + iWsCommandBufferReader->ReadPointL( point ); + iCanvasWsGc->WsDrawLineToL(point); + } + +void CHuiCanvasWsPainter::WsDrawLineByL() + { + TPoint point(0,0); + iWsCommandBufferReader->ReadPointL( point ); + iCanvasWsGc->WsDrawLineByL(point); + } + +void CHuiCanvasWsPainter::WsDrawRectL() + { + TRect rect(0,0,0,0); + iWsCommandBufferReader->ReadRectL( rect ); + + // There is a bug that CScreen::DisplayMode() returns non-alpha display mode (TSW error: ??) + // That is why WServ clears the window with the color that is opaque (0xFF000400) instead of transparent (0x00000000) + #ifdef __ALF_SYMBIAN_RWINDOW_CLEARING_BUG_WORKAROUND__ +// RDebug::Print(_L("HV: CHuiCanvasWsPainter::WsDrawRectL(). iTestBrushColor.Internal()=%x, iTestFullDisplayRect=(%d %d %d %d), rect=(%d %d %d %d) "), +// iTestBrushColor.Internal(), iTestFullDisplayRect.iTl.iX, iTestFullDisplayRect.iTl.iY,iTestFullDisplayRect.iBr.iX, iTestFullDisplayRect.iBr.iY, +// rect.iTl.iX, rect.iTl.iY,rect.iBr.iX, rect.iBr.iY); + if ( (rect == iTestFullDisplayRect) && // Is full screen rect? + (iTestBrushColor.Internal() == 0xff000400)) // Last set color is opaque dark green? + { + // RDebug::Print(_L("HV: CHuiCanvasWsPainter::WsDrawRectL(). Change brush color to 0x00000000. ")); + iCanvasWsGc->WsSetBrushColorL(TRgb(0,0,0,0)); // Replace brush color with transparent black + } + #endif + + iCanvasWsGc->WsDrawRectL(rect); + } + +void CHuiCanvasWsPainter::WsDrawText1L() + { + TPtr textValue(0,0); + TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral ); + + if (textValue.Length() == 0 || !success ) + { + return; + } + + iCanvasWsGc->WsDrawText1L(textValue,iTextParametersGeneral); + } + +void CHuiCanvasWsPainter::WsDrawText2L() + { + TPoint point(0,0); + TPtr textValue(0,0); + TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral ); + iWsCommandBufferReader->ReadPointL( point ); + + if (textValue.Length() == 0 ||!success) + { + return; + } + + iCanvasWsGc->WsDrawText2L(textValue,point,iTextParametersGeneral); + } + +void CHuiCanvasWsPainter::WsDrawText3L() + { + TRect rect(0,0,0,0); + TPtr textValue(0,0); + TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral ); + iWsCommandBufferReader->ReadRectL( rect ); + + if (textValue.Length() == 0 || !success ) + { + return; + } + + iCanvasWsGc->WsDrawText3L(textValue,rect,iTextParametersGeneral); + } + +void CHuiCanvasWsPainter::WsDrawText4L() + { + TPtr textValue(0,0); + TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral ); + iWsCommandBufferReader->ReadL( (TUint8*)&iStructDrawTextGeneral, sizeof( TStructDrawTextGeneral ) - sizeof(TInt) ); + + if (textValue.Length() == 0 || !success ) + { + return; + } + + iCanvasWsGc->WsDrawText4L(textValue, + iStructDrawTextGeneral.iRect, + iStructDrawTextGeneral.iValue1, // textBaselineOffset + iStructDrawTextGeneral.iValue2, // textAlign + iStructDrawTextGeneral.iValue3, // textMargin, + iTextParametersGeneral); + } + +void CHuiCanvasWsPainter::WsDrawText5L() + { + TPtr textValue(0,0); + TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral ); + iWsCommandBufferReader->ReadL( (TUint8*)&iStructDrawTextGeneral, sizeof( TStructDrawTextGeneral ) ); + + if (textValue.Length() == 0 || !success ) + { + return; + } + + iCanvasWsGc->WsDrawText5L(textValue, + iStructDrawTextGeneral.iRect, + iStructDrawTextGeneral.iValue1, // textBaselineOffset + iStructDrawTextGeneral.iValue3, // textAlign + iStructDrawTextGeneral.iValue4, // textMargin, + iStructDrawTextGeneral.iValue2, // textWidth + iTextParametersGeneral); + } + +void CHuiCanvasWsPainter::WsDrawTextVertical1L() + { + TInt textUp = 0; + TPtr textValue(0,0); + TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral ); + iWsCommandBufferReader->ReadInt32L( textUp ); + + if (textValue.Length() == 0 || !success ) + { + return; + } + + iCanvasWsGc->WsDrawTextVertical1L(textValue,textUp,iTextParametersGeneral); + } + +void CHuiCanvasWsPainter::WsDrawTextVertical2L() + { + TPoint point(0,0); + TInt textUp = 0; + TPtr textValue(0,0); + TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral ); + iWsCommandBufferReader->ReadPointL( point ); + iWsCommandBufferReader->ReadInt32L( textUp ); + + if (textValue.Length() == 0 || !success ) + { + return; + } + + iCanvasWsGc->WsDrawTextVertical2L(textValue,textUp,point,iTextParametersGeneral); + } + + +void CHuiCanvasWsPainter::WsDrawTextVertical3L() + { + TRect rect(0,0,0,0); + TInt textUp = 0; + TPtr textValue(0,0); + TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral); + iWsCommandBufferReader->ReadRectL( rect ); + iWsCommandBufferReader->ReadInt32L( textUp ); + + if (textValue.Length() == 0 || !success ) + { + return; + } + + iCanvasWsGc->WsDrawTextVertical3L(textValue,textUp,rect,iTextParametersGeneral); + } + +void CHuiCanvasWsPainter::WsDrawTextVertical4L() + { + TRect rect(0,0,0,0); + TInt textBaselineOffset = 0; + TInt textUp = 0; + TInt textAlign = 0; + TInt textMargin = 0; + TPtr textValue(0,0); + + TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral ); + iWsCommandBufferReader->ReadRectL( rect ); + iWsCommandBufferReader->ReadInt32L( textBaselineOffset ); + iWsCommandBufferReader->ReadInt32L( textUp ); + iWsCommandBufferReader->ReadInt32L( textAlign ); + iWsCommandBufferReader->ReadInt32L( textMargin ); + + if (textValue.Length() == 0 || !success ) + { + return; + } + + iCanvasWsGc->WsDrawTextVertical4L(textValue,rect,textBaselineOffset,textUp,textAlign,textMargin,iTextParametersGeneral); + } + +void CHuiCanvasWsPainter::WsDrawTextVertical5L() + { + TRect rect(0,0,0,0); + TInt textBaselineOffset = 0; + TInt textWidth = 0; + TInt textUp = 0; + TInt textAlign = 0; + TInt textMargin = 0; + TPtr textValue(0,0); + + iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral ); + iWsCommandBufferReader->ReadRectL( rect ); + iWsCommandBufferReader->ReadInt32L( textBaselineOffset ); + iWsCommandBufferReader->ReadInt32L( textWidth ); + iWsCommandBufferReader->ReadInt32L( textUp ); + iWsCommandBufferReader->ReadInt32L( textAlign ); + iWsCommandBufferReader->ReadInt32L( textMargin ); + + if (textValue.Length() == 0) + { + return; + } + + iCanvasWsGc->WsDrawTextVertical5L(textValue,rect,textBaselineOffset,textUp,textAlign,textMargin,textWidth,iTextParametersGeneral); + } + +void CHuiCanvasWsPainter::WsMoveToL() + { + TPoint point(0,0); + iWsCommandBufferReader->ReadPointL( point ); + iCanvasWsGc->WsMoveToL(point); + } + +void CHuiCanvasWsPainter::WsMoveByL() + { + TPoint point(0,0); + iWsCommandBufferReader->ReadPointL( point ); + iCanvasWsGc->WsMoveByL(point); + } + +void CHuiCanvasWsPainter::WsPlotL() + { + TPoint point(0,0); + iWsCommandBufferReader->ReadPointL( point ); + iCanvasWsGc->WsPlotL(point); + } + +void CHuiCanvasWsPainter::WsResetL() + { + iCanvasWsGc->WsResetL(); + + #ifdef __ALF_SYMBIAN_RWINDOW_CLEARING_BUG_WORKAROUND__ + iTestBrushColor.SetInternal(0); + #endif + } + +void CHuiCanvasWsPainter::WsSetBrushColorL() + { + TRgb color = 0; + iWsCommandBufferReader->ReadColorL( color ); + iCanvasWsGc->WsSetBrushColorL(color); + + #ifdef __ALF_SYMBIAN_RWINDOW_CLEARING_BUG_WORKAROUND__ + iTestBrushColor = color; + #endif + } + +void CHuiCanvasWsPainter::WsSetBrushOriginL() + { + TPoint point(0,0); + iWsCommandBufferReader->ReadPointL( point ); + iCanvasWsGc->WsSetBrushOriginL(point); + } + +void CHuiCanvasWsPainter::WsSetBrushStyleL() + { + TInt style = 0; + iWsCommandBufferReader->ReadInt32L( style ); + iCanvasWsGc->WsSetBrushStyleL(style); + } + +void CHuiCanvasWsPainter::WsSetClippingRegionL() + { + iTempRegion.Clear(); + iWsCommandBufferReader->ReadRegionL( iTempRegion ); + iCanvasWsGc->WsSetClippingRegionL(iTempRegion); + } + +void CHuiCanvasWsPainter::WsSetDrawModeL() + { + TInt drawMode = 0; + iWsCommandBufferReader->ReadInt32L( drawMode ); + iCanvasWsGc->WsSetDrawModeL(drawMode); + } + +void CHuiCanvasWsPainter::WsSetOriginL() + { + TPoint origin(0,0); + iWsCommandBufferReader->ReadPointL(origin); + iCanvasWsGc->WsSetOriginL(origin); + } + +void CHuiCanvasWsPainter::WsSetPenColorL() + { + TRgb color = 0; + iWsCommandBufferReader->ReadColorL( color ); + iCanvasWsGc->WsSetPenColorL(color); + } + +void CHuiCanvasWsPainter::WsSetPenStyleL() + { + TInt style = 0; + iWsCommandBufferReader->ReadInt32L( style ); + iCanvasWsGc->WsSetPenStyleL(style); + } + +void CHuiCanvasWsPainter::WsSetPenSizeL() + { + TInt width = 0; + TInt height = 0; + iWsCommandBufferReader->ReadInt32L( width ); + iWsCommandBufferReader->ReadInt32L( height ); + iCanvasWsGc->WsSetPenSizeL(width,height); + //\todo: Separate pen width and height are not yet supported + } + +void CHuiCanvasWsPainter::WsSetTextShadowColorL() + { + TRgb color = 0; + iWsCommandBufferReader->ReadColorL( color ); + iCanvasWsGc->WsSetTextShadowColorL(color); + } + +void CHuiCanvasWsPainter::WsSetCharJustificationL() + { + TInt excessWidth = 0; + TInt numGaps = 0; + iWsCommandBufferReader->ReadInt32L( excessWidth ); + iWsCommandBufferReader->ReadInt32L( numGaps ); // NumChars + iCanvasWsGc->WsSetCharJustificationL(excessWidth,numGaps); + } + +void CHuiCanvasWsPainter::WsSetWordJustificationL() + { + TInt excessWidth = 0; + TInt numGaps = 0; + iWsCommandBufferReader->ReadInt32L( excessWidth ); + iWsCommandBufferReader->ReadInt32L( numGaps ); // NumChars + iCanvasWsGc->WsSetWordJustificationL(excessWidth,numGaps); + } + +void CHuiCanvasWsPainter::WsSetUnderlineStyleL() + { + TInt value = 0; + iWsCommandBufferReader->ReadInt32L( value ); + iCanvasWsGc->WsSetUnderlineStyleL(value); + } + +void CHuiCanvasWsPainter::WsSetStrikethroughStyleL() + { + TInt value = 0; + iWsCommandBufferReader->ReadInt32L( value ); + // todo: is this magic 1000 safe offset? + iCanvasWsGc->WsSetUnderlineStyleL(value+1000); + } + + +void CHuiCanvasWsPainter::WsSetBrushPatternL() + { + TInt value = 0; + iWsCommandBufferReader->ReadInt32L( value ); + iCanvasWsGc->WsSetBrushPatternL(value); + } + +void CHuiCanvasWsPainter::WsSetFontL() + { + TInt fontId = 0; + iWsCommandBufferReader->ReadInt32L( fontId );// Font type Uid + iCanvasWsGc->WsSetFontL(fontId); + } + +void CHuiCanvasWsPainter::WsContentTagL() + { + TInt tag; + iWsCommandBufferReader->ReadInt32L( tag ); + } + +void CHuiCanvasWsPainter::WsCopyRectL() + { + TPoint point(0,0); + TRect rect(0,0,0,0); + iWsCommandBufferReader->ReadPointL( point ); + iWsCommandBufferReader->ReadRectL( rect ); + iCanvasWsGc->WsCopyRectL(point,rect); + } + +void CHuiCanvasWsPainter::WsUpdateJustificationL() + { + TPtr textValue(0,0); + iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral ); + iCanvasWsGc->WsUpdateJustificationL(textValue); + } + +void CHuiCanvasWsPainter::WsUpdateJustificationVerticalL() + { + TPtr textValue(0,0); + TInt value = 0; + + iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral ); + iWsCommandBufferReader->ReadInt32L( value ); + iCanvasWsGc->WsUpdateJustificationVerticalL(value,textValue); + } + +void CHuiCanvasWsPainter::WsSetFontNoDuplicateL() + { + TInt tempFont = 0; + iWsCommandBufferReader->ReadInt32L( tempFont ); + iCanvasWsGc->WsSetFontNoDuplicateL(tempFont); + } + + +void CHuiCanvasWsPainter::WsCopySettingsL() + { + iCanvasWsGc->WsCopySettingsL(); + } + +void CHuiCanvasWsPainter::WsSetClippingRectL() + { + TRect rect(0,0,0,0); + iWsCommandBufferReader->ReadRectL( rect ); + iCanvasWsGc->WsSetClippingRectL(rect); + } + +void CHuiCanvasWsPainter::WsCancelClippingRectL() + { + iCanvasWsGc->WsCancelClippingRectL(); + } + +void CHuiCanvasWsPainter::WsSetFadedL() + { + TInt faded = 0; + iWsCommandBufferReader->ReadInt32L( faded ); + iCanvasWsGc->WsSetFadedL(faded); + } + +void CHuiCanvasWsPainter::WsSetFadingParametersL() + { + TInt blackMap = 0; + TInt whiteMap = 0; + iWsCommandBufferReader->ReadInt32L( blackMap ); + iWsCommandBufferReader->ReadInt32L( whiteMap ); + iCanvasWsGc->WsSetFadingParametersL(blackMap,whiteMap); + } + +void CHuiCanvasWsPainter::WsFadeAreaL() + { + iTempRegion.Clear(); + iWsCommandBufferReader->ReadRegionL( iTempRegion ); + iCanvasWsGc->WsFadeAreaL(iTempRegion); + } + +void CHuiCanvasWsPainter::WsMapColorsL() + { + iCanvasWsGc->WsMapColorsL(); + } + +void CHuiCanvasWsPainter::WsSetUserDisplayModeL() + { + TInt mode = 0; + iWsCommandBufferReader->ReadInt32L( mode ); + iCanvasWsGc->WsSetUserDisplayModeL(mode); + + } + +void CHuiCanvasWsPainter::WsUseFontL() + { + TInt tempFont = 0; + iWsCommandBufferReader->ReadInt32L( tempFont ); + iCanvasWsGc->WsUseFontL(tempFont); + } + +void CHuiCanvasWsPainter::WsSetUpdateRegionL(TInt aIndex) + { + iTempRegion.Clear(); + iWsCommandBufferReader->ReadRegionL( iTempRegion ); + if (aIndex==-1) return; //TP + // Update region is modified when new buffers are added after this buffer, + // so store the region only at first read. + if (iCommandBuffers[aIndex]->iChanged && iCommandBuffers[aIndex]->iUpdateRegion.Count() == 0) + { + // Check first that the coordiates are not insane (sometimes thay are) + TInt count = iTempRegion.Count(); + TRect displayRect = iCanvasVisual->DisplayRect(); + for (TInt i=count-1; i>=0; i--) + { + TRect rect = iTempRegion[i]; + TRect screen = iCanvasVisual->Display()->VisibleArea(); + if (rect.Intersects(screen) || rect == screen) + { + // - Sometimes updateregion is outiside window (WSERV...why?!) + // We clip it here to avoid ui probs. + // - Lets remove this for now, this seems to break scrollbars again + // when window parent-child relations work.. + // - Hmm, should we add this anyway because now the idle softkeys are lost again in landscape mode ? + // - Added again after WSERV fix in the window parent-child relations +#ifndef HUI_DISABLE_CANVAS_VISUAL_CLIPPING + rect.Intersection(displayRect); +#endif + iCommandBuffers[aIndex]->iUpdateRegion.AddRect(rect); + iCommandBuffers[aIndex]->iOriginalUpdateRegion.AddRect(rect); + } + else + { +#ifdef _DEBUG + RDebug::Print(_L("CHuiCanvasWsPainter::WsSetUpdateRegionL: Incorrect update region removed from buffer, this should not happen !")); +#endif + } + } + + // Combine areas that are next to each others + iCommandBuffers[aIndex]->iUpdateRegion.Tidy(); + iCommandBuffers[aIndex]->iOriginalUpdateRegion.Tidy(); + + // Subtract this buffers update area from previous buffers update areas to avoid overdraw + + // TODO: Subtraction is for now commented out because it seems to cause UI problems, especially + // with lists with scrollbar. Try e.g. opening image from filebrowser, then press back and + // scrollbar area is often corrupted. This happens (probaply) because first command buffer contains + // real background drawing under scrollbar, but partial command buffers do not contain it although + // their update region extends below scrollbar. + // + // This issue should be fixed because leaving subration undone causes performance to be worse. + // + + /* + if (aIndex > 0) + { + for (TInt i=aIndex; i>0; i--) + { + TInt previous = aIndex - 1; + iCommandBuffers[previous]->iUpdateRegion.SubRegion(iCommandBuffers[aIndex]->iUpdateRegion); + iCommandBuffers[previous]->iUpdateRegion.Tidy(); + } + } +*/ + } + } + +void CHuiCanvasWsPainter::WsSetShapeRegionL( TInt aIndex ) + { + iTempRegion.Clear(); + iWsCommandBufferReader->ReadRegionL( iTempRegion ); + + + // If there is a shape region, get it only from the newest buffer. + // This is the case when the buffer has just been added to the canvas visual. + + if(aIndex == iCommandBuffers.Count() - 1) + { + // Note: The "set shape" command looks to be used only if it really is different from + // the window rect. So there is no need to check if the shape region is relevant. + iShapeRegion.Copy(iTempRegion); + + // note: iUpdateRegion will be updated later, set flags to indicate pending + iShapeRegionClearingPending = ETrue; + iShapeRegionClippingPending = ETrue; + } + + + #ifdef _DEBUG + if (iShapeRegion.Count() == 0 && iTempRegion.Count() > 0) + { + HUI_DEBUG(_L("CHuiCanvasWsPainter::WsSetShapeRegionL. Error: iShapeRegion not set by any command buffer! However, there exists at least one command buffer that has shape region command.")); + } + #endif + } + +void CHuiCanvasWsPainter::DoDigestPaddingL() + { + TUint8 padding = iWsCommandBufferReader->ReadInt8L(); + while( padding-- ) + { +#ifdef _DEBUG + if ( iWsCommandBufferReader->ReadInt8L() != 0 ) + { + RDebug::Print(_L("CHuiCanvasWsPainter::DigestPaddingL - Padding error")); + USER_INVARIANT(); + } +#else + iWsCommandBufferReader->ReadInt8L(); +#endif + } + } + +void CHuiCanvasWsPainter::DestroyBuffer(TInt aIndex) + { + CHuiCanvasCommandBuffer* buffer = iCommandBuffers[aIndex]; + + TTime now; + now.UniversalTime(); + TInt lifetimeInMs = now.MicroSecondsFrom( buffer->iCreationTime ).Int64()/1000; + if (lifetimeInMs > 0 && lifetimeInMs < KHuiCanvasDisableRenderBufferHandleInterval) + { + /* Check and disable render buffer if needed */ + if (iCommandBuffers.Count() == 2) + { + EnableRenderBufferIfNeeded(EFalse); + } + } + + iCommandBuffers.Remove(aIndex); + delete buffer; + } + + +TBool CHuiCanvasWsPainter::RemoveRedundantBuffers() + { + TBool didRemoveBuffers = EFalse; + TInt originalBufferCount = iCommandBuffers.Count(); + + RemoveBuffersWithoutRealDrawing(); + RemoveBuffersWithOldDisplayRect(); + RemoveBuffersWithEmptyUpdateRegion(); + RemoveBuffersWithOverlappingUpdateRegion(); + + didRemoveBuffers = (originalBufferCount != iCommandBuffers.Count()); + return didRemoveBuffers; + } + +void CHuiCanvasWsPainter::RemoveBuffersWithoutRealDrawing() + { + TInt bufferCount = iCommandBuffers.Count(); + for (TInt cb = bufferCount - 1; cb >= 0; cb--) + { + CHuiCanvasCommandBuffer* buffer = iCommandBuffers[cb]; + TInt flags = buffer->iStatusFlags; + if ((flags & EHuiCanvasBufferStatusScanned) && !(flags & EHuiCanvasBufferContainsDrawing)) + { + DestroyBuffer(cb); + } + } + } + + +void CHuiCanvasWsPainter::RemoveBuffersWithOldDisplayRect() + { + TInt bufferCount = iCommandBuffers.Count(); + for (TInt cb = bufferCount - 1; cb >= 0; cb--) + { + CHuiCanvasCommandBuffer* buffer = iCommandBuffers[cb]; + if (buffer->iOriginalDisplayRect.Round() != iCanvasVisual->DisplayRect().Round()) + { + DestroyBuffer(cb); + } + } + } + +void CHuiCanvasWsPainter::RemoveBuffersWithEmptyUpdateRegion() + { + TInt bufferCount = iCommandBuffers.Count(); + for (TInt cb = bufferCount - 1; cb >= 0; cb--) + { + CHuiCanvasCommandBuffer* buffer = iCommandBuffers[cb]; + if (buffer->iOriginalUpdateRegion.Count() == 0) + { + DestroyBuffer(cb); + } + } + } + +void CHuiCanvasWsPainter::RemoveBuffersWithOverlappingUpdateRegion() + { + // Check possibly overlapping update regions + TBool arraysChanged = ETrue; + while (arraysChanged) + { + arraysChanged = EFalse; + iTempRegion.Clear(); + + // Loop all buffers + TInt bufferCount = iCommandBuffers.Count(); + for (TInt cb = bufferCount - 1; cb >= 0; cb--) + { + if (arraysChanged) + { + break; + } + + CHuiCanvasCommandBuffer* cmdbuffer = iCommandBuffers[cb]; + for (TInt j=0; j < cmdbuffer->iOriginalUpdateRegion.Count();j++) + { + iTempRegion.AddRect(cmdbuffer->iOriginalUpdateRegion[j]); + } + + // Check older buffers for overlapping regions against current buffer + if (cb > 0) + { + for (TInt i = cb - 1; i >= 0; i--) + { + if (arraysChanged) + { + break; + } + + CHuiCanvasCommandBuffer* previousCommands = iCommandBuffers[i]; + // Keep count how many subregions of the prevous command are contained inside current command buffer region + TInt coveredRegionCount = 0; + for (TInt k=0; k < previousCommands->iOriginalUpdateRegion.Count();k++) + { + iTempCurrentSubRegion.Clear(); + iTempIntersectingRegion.Clear(); + iTempCurrentSubRegion.AddRect(previousCommands->iOriginalUpdateRegion[k]); + iTempIntersectingRegion.Intersection(iTempRegion, iTempCurrentSubRegion); + iTempIntersectingRegion.Tidy(); + + if (iTempIntersectingRegion.Count() == 1) + { + if (iTempIntersectingRegion[0] == previousCommands->iOriginalUpdateRegion[k]) + { + coveredRegionCount++; + // If all regions were overlapping agains current buffer, we can delete this. + if (coveredRegionCount == previousCommands->iOriginalUpdateRegion.Count()) + { + DestroyBuffer(i); + arraysChanged = ETrue; + break; + } + } + else + { + // There is no reason to continue with this one if even one of its subregions + // is outside overlapping region. + break; + } + } + } + } + } + } + } + } + +CHuiCanvasGc& CHuiCanvasWsPainter::CanvasGc() const + { + return iCanvasWsGc->CanvasGc(); + } + +TInt CHuiCanvasWsPainter::PaintedAreaCount() const + { + TInt paintedAreaCount = 0; + TInt bufferCount = iCommandBuffers.Count(); + for (TInt cb = 0; cb < bufferCount; cb++) + { + paintedAreaCount += iCommandBuffers[cb]->iUpdateRegion.Count(); + } + return paintedAreaCount; + } + +THuiCanvasPaintedArea CHuiCanvasWsPainter::PaintedArea(TInt aIndex) + { + THuiCanvasPaintedArea area; + area.iPaintType = EHuiCanvasPaintTypeOpaque; + area.iFlags = 0; + + TInt firstIndexInCurrentBuffer = 0; + TInt lastIndexInCurrentBuffer = 0; + TInt indexCounter = 0; + + TInt bufferCount = iCommandBuffers.Count(); + for (TInt cb = 0; cb < bufferCount; cb++) + { + TInt updateRegionCount = iCommandBuffers[cb]->iUpdateRegion.Count(); + if (updateRegionCount) + { + firstIndexInCurrentBuffer = indexCounter; + lastIndexInCurrentBuffer = firstIndexInCurrentBuffer + updateRegionCount - 1; + + if ((firstIndexInCurrentBuffer <= aIndex) && (aIndex <= lastIndexInCurrentBuffer)) + { + TInt localIndex = aIndex - firstIndexInCurrentBuffer; + area.iPaintedRect = iCommandBuffers[cb]->iUpdateRegion[localIndex]; + break; + } + indexCounter += updateRegionCount; + } + } + return area; + } + +TInt CHuiCanvasWsPainter::SetCapturingBufferL(CFbsBitmap* aTarget) + { + TInt result = iCanvasWsGc->SetCapturingBufferL(aTarget); + + if ( !aTarget ) + { + // We may have switched to another GC - so to ensure that + // all are released, we will send this request to all. + CHuiCanvasWsGc* gcs[] = + { + iCanvasWsBitGc, + iCanvasWsSwGc, + iCanvasWsHwGc + }; + TInt count = sizeof(gcs) / sizeof(CHuiCanvasWsGc*); + for ( TInt i = count - 1; i >= 0; --i ) + { + if ( gcs[i] && gcs[i] != iCanvasWsGc ) + { + gcs[i]->SetCapturingBufferL(NULL); + } + } + } + + return result; + } + +TRect CHuiCanvasWsPainter::DirtyRect() const + { + iTempRegion.Clear(); + TInt bufferCount = iCommandBuffers.Count(); + for (TInt cb = 0; cb < bufferCount; cb++) + { + const CHuiCanvasCommandBuffer& cmdbuffer = *iCommandBuffers[cb]; + + // Report only changed buffers. This should be ok as long as + // this method is only used when scanning visual tree and + // thus visual (and buffer) changed flags are in correct states. + if (cmdbuffer.iChanged) + { + iTempRegion.Union(cmdbuffer.iUpdateRegion); + } + } + return iTempRegion.BoundingRect(); + } + +TBool CHuiCanvasWsPainter::IsBufferCompletelyOutisideClippingRegion(const CHuiCanvasCommandBuffer& aCommandbuffer) const + { + CHuiGc* gc = iCanvasWsGc->CanvasGc().Gc(); + if (gc && gc->ClipRegion().Count()) + { + // This is a bit tricky part, gc clipregion is in transformed coordinates but our update region is not. + // So we must transform our update region before we can compare it to gc clipping region and + // know if it falls comletely outside it or not. + iTempRegion.Clear(); + for (TInt i=0; iTransformDirtyRect(transformed); + iTempRegion.AddRect(transformed.Round()); + } + + CHuiCanvasGc::TClipRectVisibility visibility = iCanvasWsGc->CanvasGc().IsClipped(iTempRegion, gc->ClipRegion()); + + if (visibility == CHuiCanvasGc::EFullyOutside) + { + return ETrue; + } + } + + return EFalse; + } + +TInt CHuiCanvasWsPainter::EnableRenderBuffer(TBool aEnable) + { + if (aEnable != iCanvasWsGc->IsRenderBufferEnabled()) + { + if (aEnable) + { + // Must redraw all buffers to render buffer at next frame + RenewAllBuffers(); + } + return iCanvasWsGc->EnableRenderbuffer(aEnable); + } + else + { + return KErrNone; + } + } + +void CHuiCanvasWsPainter::EnableRenderBufferIfNeeded(TBool aEnable) + { + if (!KHuiCanvasAutomaticRenderBufferUsage || !CHuiStatic::Renderer().Allows(EHuiRenderPluginAllowVisualPBufferSurfaces)) + { + return; + } + + if (aEnable) + { + if (iAutomaticRenderBufferUsage && !iCanvasWsGc->IsRenderBufferEnabled() && HasOldCommandBuffers(KHuiCanvasEnableRenderBufferHandleInterval)) + { + RDebug::Print(_L("CHuiCanvasWsPainter::EnableRenderBufferIfNeeded: Enabling renderbuffer")); + EnableRenderBuffer(ETrue); + iAutomaticRenderBufferUsage = ETrue; + } + } + else + { + if (iCanvasWsGc->IsRenderBufferEnabled()) + { + RDebug::Print(_L("CHuiCanvasWsPainter::EnableRenderBufferIfNeeded: Disabling renderbuffer")); + EnableRenderBuffer(EFalse); + iAutomaticRenderBufferUsage = ETrue; + } + } + } + +void CHuiCanvasWsPainter::SelectGcL() + { + TBool hasUnsupportedCommands = EFalse; + TInt bufferCount = iCommandBuffers.Count(); + for (TInt cb = 0; cb < bufferCount; cb++) + { + const CHuiCanvasCommandBuffer& cmdbuffer = *iCommandBuffers[cb]; + if (cmdbuffer.iContainsUnsupportedCommands) + { + hasUnsupportedCommands = ETrue; + break; + } + } + + THuiMemoryLevel memoryLevel; + if ( iCanvasVisual ) // in constructor, iCanvasVisual == NULL + { + memoryLevel = iCanvasVisual->Env().MemoryLevel(); + } + else + { + memoryLevel = CHuiStatic::Env().MemoryLevel(); + } + + CHuiCanvasWsGc* oldGc = iCanvasWsGc; + + if (memoryLevel <= EHuiMemoryLevelLowest) + { + if (!iCanvasWsGc || iCanvasWsGc != iCanvasWsBitGc) + { + // Fallback to the BIT GDI mode + if (!iCanvasWsBitGc) + { + iCanvasWsBitGc = CHuiCanvasWsBitGc::NewL(); + } + iCanvasWsGc = iCanvasWsBitGc; + // Must redraw all buffers to render buffer at next frame + RenewAllBuffers(); + } + } + else if (hasUnsupportedCommands && (!iCanvasWsGc || + iCanvasWsGc != iCanvasWsSwGc)) + { + // Fallback to the SW mode + if (!iCanvasWsSwGc) + { + iCanvasWsSwGc = CHuiCanvasWsSwGc::NewL(); + } + iCanvasWsGc = iCanvasWsSwGc; + // Must redraw all buffers to render buffer at next frame + RenewAllBuffers(); + } + else if (!hasUnsupportedCommands && (!iCanvasWsGc || + iCanvasWsGc != iCanvasWsHwGc)) + { + // Return to the HW accelerated mode + if (!iCanvasWsHwGc) + { + iCanvasWsHwGc = CHuiCanvasWsHwGc::NewL(); + } + iCanvasWsGc = iCanvasWsHwGc; + // Must redraw all buffers to render buffer at next frame + RenewAllBuffers(); + } + else + { + // We are good + } + + // Clear caches of non-used GCs + if ( oldGc && oldGc != iCanvasWsGc ) + { + oldGc->ClearCache(); + } + + #ifdef HUI_DEBUG_TRACK_DRAWING + CHuiCanvasWsGc* realGc = iCanvasWsGc; + iCanvasWsGc = CHuiCanvasDebugWsGc::NewL( realGc, *iCommandDebugger ); + #endif + } + +void CHuiCanvasWsPainter::RenewAllBuffers() + { + ClearAllBufferStatusFlags(EHuiCanvasBufferStatusAll); + SetAllBufferStatusFlags(EHuiCanvasBufferStatusNew); + + if (iCanvasVisual) + { + iCanvasVisual->SetChanged(); + } + } + +void CHuiCanvasWsPainter::UpdateBufferUpdateRegions(TPoint aPos) + { + // iUpdateRegion is in screen coordinates. If visual moves position, iUpdateRegion + // should be updated as well. Otherwise visual will encounter clipping. + for (TInt cb = 0; cb < iCommandBuffers.Count(); cb++) + { + if (iCommandBuffers[cb]->iPositionForUpdateRegion != aPos && !iCommandBuffers[cb]->iUpdateRegion.IsEmpty() ) + { + TPoint deltaPos = aPos - iCommandBuffers[cb]->iPositionForUpdateRegion; + iCommandBuffers[cb]->iUpdateRegion.Offset(deltaPos); + iCommandBuffers[cb]->iPositionForUpdateRegion = aPos; + iCommandBuffers[cb]->ClearStatusFlags(EHuiCanvasBufferStatusAll); + iCommandBuffers[cb]->SetStatusFlags(EHuiCanvasBufferStatusNew); + } + } + } + +void CHuiCanvasWsPainter::SetMemoryLevel(THuiMemoryLevel /*aLevel*/) + { + TRAP_IGNORE(SelectGcL()); + } +