diff -r 10e98eab6f85 -r a359256acfc6 webengine/osswebengine/WebCore/platform/symbian/bitmap/SyncDecodeThread.cpp --- a/webengine/osswebengine/WebCore/platform/symbian/bitmap/SyncDecodeThread.cpp Fri Jul 03 15:54:40 2009 +0100 +++ b/webengine/osswebengine/WebCore/platform/symbian/bitmap/SyncDecodeThread.cpp Thu Aug 27 07:44:59 2009 +0300 @@ -40,6 +40,7 @@ TInt iMaskHandle; }; +enum DecoderState {ENewDecodeRequest, EDecodeInProgress, EDecoderIdle}; class CSynDecoder : public CActive { public: // Constructors and destructor @@ -47,25 +48,35 @@ virtual ~CSynDecoder(); public: - TInt Open(BmElem* aElem); + void Open(const TDesC8& aData, TRequestStatus *status); + void Lock() { iDecoderLock.Wait(); } + void Release() { iDecoderLock.Signal(); } private: // From base class CActive void DoCancel(); void RunL(); TInt RunError( TInt aError ); void SignalParent( TInt aError ); + void StartDecodeL(); + void SetIdle(); private: // Private constructors CSynDecoder(); - void ConstructL() {} + void ConstructL(); private: // Data - BmElem* iElem; // not owned - CImageDecoder* iDecoder; // owned - CMaskedBitmap* iBitmap; // owned + BmElem iElem; + CImageDecoder* iDecoder; + CMaskedBitmap* iBitmap; + RFastLock iDecoderLock; + DecoderState iDecodeState; + RThread syncThread; + +friend class CSynDecodeThread; }; // FORWARD DECLARATIONS +CSynDecoder *CSynDecodeThread::iSyncDecoder = NULL; // ============================= LOCAL FUNCTIONS =============================== @@ -80,6 +91,12 @@ CActiveScheduler::Add( this ); } +void CSynDecoder::ConstructL() +{ + User::LeaveIfError(iDecoderLock.CreateLocal()); + SetIdle(); +} + CSynDecoder* CSynDecoder::NewL() { CSynDecoder* self = new (ELeave) CSynDecoder(); @@ -94,46 +111,67 @@ Cancel(); delete iDecoder; delete iBitmap; + iDecoderLock.Close(); } // ----------------------------------------------------------------------------- -// OpenL +// Decode - Decode request submitted from client thread // ----------------------------------------------------------------------------- -TInt CSynDecoder::Open(BmElem* aElem) +void CSynDecoder::Open(const TDesC8& aData, TRequestStatus *status) +{ + iElem.iRequestStatus = status; + iElem.iData.Set(aData); + iElem.iParentThreadId = RThread().Id(); + iElem.iBitmapHandle = 0; + iElem.iMaskHandle = 0; + iDecodeState = ENewDecodeRequest; +} + +void CSynDecoder::SetIdle() { - iElem = aElem; - // reset decoder - TRAPD( err, - iDecoder = CImageDecoder::DataNewL(CEikonEnv::Static()->FsSession(), iElem->iData); - iBitmap = CMaskedBitmap::NewL(); - ); - if( err != KErrNone ) - return err; + iDecodeState = EDecoderIdle; + if(!IsActive()) { + iStatus = KRequestPending; + SetActive(); + } +} +void CSynDecoder::StartDecodeL() +{ + if(iDecoder) { + delete iDecoder; + iDecoder = NULL; + } + if(iBitmap) { + delete iBitmap; + iBitmap = NULL; + } + + iDecoder = CImageDecoder::DataNewL(CEikonEnv::Static()->FsSession(), iElem.iData); + iBitmap = CMaskedBitmap::NewL(); + TFrameInfo frameInfo = iDecoder->FrameInfo( 0 ); - + TInt err = KErrNone; if( frameInfo.iFlags & TFrameInfo::ETransparencyPossible ) { TDisplayMode maskmode = (frameInfo.iFlags & TFrameInfo::EAlphaChannel) ? EGray256 : EGray2; - err = iBitmap->Create( frameInfo.iOverallSizeInPixels, EColor64K, maskmode ); } else err = iBitmap->Create( frameInfo.iOverallSizeInPixels, EColor64K ); - // - if( err != KErrNone ) - return err; - // start decoding + User::LeaveIfError(err); + + // start decoding CFbsBitmap& dstBitmap = iBitmap->BitmapModifyable(); - CFbsBitmap& dstMask = iBitmap->MaskModifyable(); - + CFbsBitmap& dstMask = iBitmap->MaskModifyable(); if( ( frameInfo.iFlags & TFrameInfo::ETransparencyPossible ) && dstMask.Handle() ) iDecoder->Convert( &iStatus, dstBitmap, dstMask, 0 ); else { dstMask.Reset(); iDecoder->Convert( &iStatus, dstBitmap, 0 ); } + + iDecodeState = EDecodeInProgress; SetActive(); - return KErrNone; } // ----------------------------------------------------------------------------- @@ -143,25 +181,31 @@ { iDecoder->Cancel(); SignalParent( KErrCancel ); + SetIdle(); } // ----------------------------------------------------------------------------- // CSynDecoder::RunL // ----------------------------------------------------------------------------- void CSynDecoder::RunL() -{ - SignalParent( iStatus.Int() ); - - if( iStatus.Int() == KErrNone ) { - iElem->iBitmapHandle = iBitmap->Bitmap().Handle(); - iElem->iMaskHandle = iBitmap->Mask().Handle(); - - RThread self; - self.Suspend(); - self.Close(); - // destroy - CActiveScheduler::Stop(); - } +{ + switch(iDecodeState) + { + case ENewDecodeRequest: + StartDecodeL(); // start async decode + break; + case EDecodeInProgress: + if( iStatus.Int() == KErrNone ) { + iElem.iBitmapHandle = iBitmap->Bitmap().Handle(); + iElem.iMaskHandle = iBitmap->Mask().Handle(); + } + + SignalParent(iStatus.Int()); + SetIdle(); + break; + default: + SetIdle(); + } } // ----------------------------------------------------------------------------- @@ -169,7 +213,8 @@ // ----------------------------------------------------------------------------- TInt CSynDecoder::RunError(TInt aError) { - SignalParent( aError ); + SignalParent(aError); + SetIdle(); return KErrNone; } @@ -179,13 +224,11 @@ void CSynDecoder::SignalParent(TInt aError) { RThread parent; - parent.Open(iElem->iParentThreadId); - parent.RequestComplete(iElem->iRequestStatus, aError ); - parent.Close(); + parent.Open(iElem.iParentThreadId); + parent.RequestComplete(iElem.iRequestStatus, aError ); + parent.Close(); +} - if (aError != KErrNone) - CActiveScheduler::Stop(); -} CSynDecodeThread* CSynDecodeThread::NewL() { @@ -201,46 +244,45 @@ } CSynDecodeThread::~CSynDecodeThread() -{ - if(iUp) { - iDecoderThread.Resume(); - iDecoderThread.Kill(KErrNone); - iDecoderThread.Close(); - } - delete iElem; +{ + CActiveScheduler::Stop(); + iDecoderThread.Close(); +} + +void CSynDecodeThread::ConstructL() +{ + _LIT(KThreadName, "ImgDecoder"); + User::LeaveIfError(iDecoderThread.Create(KThreadName, CSynDecodeThread::ScaleInThread, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, NULL)); + iDecoderThread.SetPriority(EPriorityMore); + TRequestStatus status = KRequestPending; + iDecoderThread.Rendezvous(status); + iDecoderThread.Resume(); + User::WaitForRequest(status); + User::LeaveIfError(status.Int()); } -void CSynDecodeThread::ConstructL() +TInt CSynDecodeThread::Decode(const TDesC8& aData) { -} - -TInt CSynDecodeThread::Decode(const TDesC8& aData, TRequestStatus* aRequestStatus) -{ - iElem = new (ELeave) BmElem; - iElem->iData.Set( aData ); - iElem->iParentThreadId = RThread().Id(); - iElem->iRequestStatus = aRequestStatus; + iSyncDecoder->Lock(); + + //notify decoder thread about new request + TRequestStatus status = KRequestPending; + iSyncDecoder->Open(aData, &status); + TRequestStatus *ps = &(iSyncDecoder->iStatus); + iDecoderThread.RequestComplete(ps, KErrNone); - TBuf<20> randName; - TTime t; - t.HomeTime(); - randName.Num( I64INT(t.Int64()) ); + //wait for decode complete + User::WaitForRequest(status); - TInt err = iDecoderThread.Create(randName, CSynDecodeThread::ScaleInThread, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, iElem); - if (err==KErrNone) { - iUp = ETrue; - iDecoderThread.SetPriority(EPriorityMore); - *aRequestStatus = KRequestPending; - iDecoderThread.Resume(); - } - return err; + iSyncDecoder->Release(); + return status.Int(); } void CSynDecodeThread::Handle(TInt& aBitmapHandle, TInt& aMaskHandle) { - aBitmapHandle = iElem->iBitmapHandle; - aMaskHandle = iElem->iMaskHandle; + aBitmapHandle = iSyncDecoder->iElem.iBitmapHandle; + aMaskHandle = iSyncDecoder->iElem.iMaskHandle; } TInt CSynDecodeThread::ScaleInThread(TAny *aPtr) @@ -248,26 +290,23 @@ CTrapCleanup* cleanup = CTrapCleanup::New(); CActiveScheduler* as = new CActiveScheduler; CActiveScheduler::Install(as); - - CSynDecoder* decoder = NULL; - RFbsSession fbs; fbs.Connect(); - BmElem* elem = (BmElem*)aPtr; - TRAPD(err, decoder = CSynDecoder::NewL()); - - if (err == KErrNone && (err = decoder->Open(elem))== KErrNone ) - CActiveScheduler::Start(); - else { - RThread parent; - parent.Open(elem->iParentThreadId); - parent.RequestComplete(elem->iRequestStatus, err); - parent.Close(); + // start event loop + TRAPD(err, iSyncDecoder = CSynDecoder::NewL()); + if (err == KErrNone) { + // wait for decode request from client threads + RThread().Rendezvous(KErrNone); + CActiveScheduler::Start(); } - + else { + RThread().Rendezvous(err); + } + + // thread shutdown delete as; - delete decoder; + delete iSyncDecoder; delete cleanup; fbs.Disconnect(); return err;