1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/windowing/windowserver/nonnga/SERVER/Direct.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,613 @@
1.4 +// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Direct Screen Access class, to allow the client to draw directly to the screen
1.18 +//
1.19 +//
1.20 +
1.21 +#include <e32base.h>
1.22 +#include "Direct.H"
1.23 +#include "server.h"
1.24 +#include "rootwin.h"
1.25 +#include "wstop.h"
1.26 +#include "panics.h"
1.27 +#include <e32msgqueue.h>
1.28 +
1.29 +const TInt KMsgQueueLength = 1;
1.30 +
1.31 +static TBool RegionsMatch(const TRegion & aOne, const TRegion & aTwo);
1.32 +
1.33 +
1.34 +CDsaMsgQueue* CDsaMsgQueue::NewL(CWsDirectScreenAccess* aDirect)
1.35 + {
1.36 + CDsaMsgQueue* self = new(ELeave)CDsaMsgQueue;
1.37 + CleanupStack::PushL(self);
1.38 + self->ConstructL(aDirect);
1.39 + CleanupStack::Pop(self);
1.40 + return self;
1.41 + }
1.42 +
1.43 +CDsaMsgQueue::CDsaMsgQueue()
1.44 +{}
1.45 +
1.46 +CDsaMsgQueue::~CDsaMsgQueue()
1.47 + {
1.48 + delete iAborted;
1.49 + iSendQueue.Close();
1.50 + iRecQueue.Close();
1.51 + }
1.52 +
1.53 +void CDsaMsgQueue::ConstructL(CWsDirectScreenAccess* aDirect)
1.54 + {
1.55 + iAborted=new(ELeave) CWsAbortDirect(aDirect,this);
1.56 + }
1.57 +
1.58 +void CDsaMsgQueue::Cancel()
1.59 + {
1.60 + //purge the queue of data
1.61 + TInt ret = KErrNone;
1.62 + do
1.63 + {
1.64 + TInt data = 0;
1.65 + ret = iRecQueue.Receive(&data,sizeof(TInt));
1.66 + }while(ret == KErrNone);
1.67 + iAborted->Cancel();
1.68 + }
1.69 +
1.70 +TInt CDsaMsgQueue::Send(TInt aData)
1.71 + {
1.72 + return iSendQueue.Send(&aData,sizeof(TInt));
1.73 + }
1.74 +
1.75 +TInt CDsaMsgQueue::CreateSendQueue()
1.76 + {
1.77 + if(iSendQueue.Handle() == 0)
1.78 + {
1.79 + return iSendQueue.CreateGlobal(KNullDesC,KMsgQueueLength,sizeof(TInt), EOwnerProcess);
1.80 + }
1.81 + else
1.82 + {
1.83 + return 0;
1.84 + }
1.85 + }
1.86 +
1.87 +TInt CDsaMsgQueue::CreateRecQueue()
1.88 + {
1.89 + if(iRecQueue.Handle() == 0)
1.90 + {
1.91 + return iRecQueue.CreateGlobal(KNullDesC,KMsgQueueLength,sizeof(TInt), EOwnerProcess);
1.92 + }
1.93 + else
1.94 + {
1.95 + return 0;
1.96 + }
1.97 + }
1.98 +
1.99 +RMsgQueueBase* CDsaMsgQueue::SendQueue()
1.100 + {
1.101 + return &iSendQueue;
1.102 + }
1.103 +
1.104 +RMsgQueueBase* CDsaMsgQueue::RecQueue()
1.105 + {
1.106 + return &iRecQueue;
1.107 + }
1.108 +
1.109 +void CDsaMsgQueue::Started()
1.110 + {
1.111 + iAborted->Started();
1.112 + }
1.113 +
1.114 +void CDsaMsgQueue::Complete()
1.115 + {
1.116 + iAborted->Complete(RDirectScreenAccess::ETerminateCancel);
1.117 + }
1.118 +
1.119 +void CDsaMsgQueue::CompleteAbort()
1.120 + {
1.121 + iAborted->Complete(KErrNone);
1.122 + }
1.123 +
1.124 +TInt CDsaMsgQueue::ReceiveData()
1.125 + {
1.126 + TInt data = 0;
1.127 + iRecQueue.Receive(&data,sizeof(TInt));
1.128 + return data;
1.129 + }
1.130 +
1.131 +/*CWsAbortDirect*/
1.132 +
1.133 +CWsAbortDirect::CWsAbortDirect(CWsDirectScreenAccess* aDirect,CDsaMsgQueue* aParent) : CActive(EDirectAbort), iDirect(aDirect),iParent(aParent)
1.134 + {
1.135 + CActiveScheduler::Add(this);
1.136 + }
1.137 +
1.138 +CWsAbortDirect::~CWsAbortDirect()
1.139 + {
1.140 + Cancel();
1.141 + }
1.142 +
1.143 +void CWsAbortDirect::Started()
1.144 + {
1.145 + iStatus=KRequestPending;
1.146 + TRequestStatus& status = iStatus;
1.147 + iParent->RecQueue()->NotifyDataAvailable(status);
1.148 + SetActive();
1.149 + }
1.150 +
1.151 +void CWsAbortDirect::RunL()
1.152 + {
1.153 + iParent->ReceiveData();
1.154 + iParent->RecQueue()->CancelDataAvailable();
1.155 + iDirect->Aborted();
1.156 + }
1.157 +
1.158 +void CWsAbortDirect::DoCancel()
1.159 + {
1.160 + iParent->RecQueue()->CancelDataAvailable();
1.161 + if (iStatus==KRequestPending)
1.162 + {
1.163 + Complete(KErrNone);
1.164 + }
1.165 + }
1.166 +
1.167 +void CWsAbortDirect::Complete(TInt aReason)
1.168 + {
1.169 + if(IsActive())
1.170 + {
1.171 + TRequestStatus* status=&iStatus;
1.172 + RThread().RequestComplete(status,aReason);
1.173 + }
1.174 + }
1.175 +
1.176 +
1.177 +/*CWsDirectScreenAccess*/
1.178 +
1.179 +CWsDirectScreenAccess* CWsDirectScreenAccess::NewL(CWsClient* aOwner)
1.180 + {
1.181 + CWsDirectScreenAccess* self = new(ELeave) CWsDirectScreenAccess(aOwner);
1.182 + CleanupStack::PushL(self);
1.183 + self->ConstructL();
1.184 + CleanupStack::Pop(self);
1.185 + return self;
1.186 + }
1.187 +
1.188 +CWsDirectScreenAccess::~CWsDirectScreenAccess()
1.189 + {
1.190 + DeleteRegionSyncWatchcat();
1.191 + iFrozenRegion.Close();
1.192 + iVisible.Close();
1.193 + if (iStatus!=EDirectStatusTimeNotCreated)
1.194 + {
1.195 + if (iStatus==EDirectStatusRunning)
1.196 + AbortNow();
1.197 + if (iStatus>=EDirectStatusAborted)
1.198 + CorrectScreen();
1.199 + }
1.200 + WS_ASSERT_DEBUG(!OnQueue(), EWsPanicDirectScreenAccess);
1.201 + delete iMsgQueue;
1.202 + }
1.203 +
1.204 +void CWsDirectScreenAccess::ConstructL()
1.205 + {
1.206 + NewObjL();
1.207 + iMsgQueue = CDsaMsgQueue::NewL(this);
1.208 + iStatus=EDirectStatusNone;
1.209 + }
1.210 +
1.211 +void CWsDirectScreenAccess::Request(TInt handle)
1.212 + {
1.213 + if (iStatus!=EDirectStatusNone)
1.214 + {
1.215 + if (iStatus==EDirectStatusCompleted)
1.216 + {
1.217 + iMsgQueue->Cancel();
1.218 + }
1.219 + else
1.220 + {
1.221 + iWsOwner->PPanic(EWservPanicDirectMisuse);
1.222 + }
1.223 + }
1.224 + iWsOwner->HandleToClientWindow(handle,&iWin);
1.225 + iScreen=iWin->Screen();
1.226 + STACK_REGION region;
1.227 + iWin->GenerateTopRegion(region);
1.228 + const TInt regionCount=region.Count();
1.229 + region.Close();
1.230 + SetReply(regionCount);
1.231 + iStatus=EDirectStatusInitialising;
1.232 + }
1.233 +
1.234 +void CWsDirectScreenAccess::GetRegion(TInt aNumRects)
1.235 + {
1.236 +#if defined(_DEBUG)
1.237 + if (iStatus!=EDirectStatusInitialising)
1.238 + iWsOwner->PPanic(EWservPanicDirectMisuse);
1.239 +#endif
1.240 + STACK_REGION region;
1.241 + iWin->GenerateTopRegion(region);
1.242 + const TInt regionCount=region.Count();
1.243 + if (region.Count()==aNumRects)
1.244 + {
1.245 + iVisible.Copy(region);
1.246 + if (iVisible.CheckError())
1.247 + {
1.248 + iStatus=EDirectStatusNone;
1.249 + SetReply(KErrNotReady);
1.250 + }
1.251 + else
1.252 + {
1.253 + TPtrC8 rectList(REINTERPRET_CAST(const TUint8*,region.RectangleList()),region.Count()*sizeof(TRect));
1.254 + CWsClient::ReplyBuf(rectList);
1.255 + iStatus=EDirectStatusRunning;
1.256 + Initiate();
1.257 + iMsgQueue->Started();
1.258 + SetReply(KMaxTInt);
1.259 + }
1.260 + }
1.261 + else
1.262 + {
1.263 + SetReply(region.Count());
1.264 + }
1.265 + region.Close();
1.266 + }
1.267 +
1.268 +void CWsDirectScreenAccess::Cancel()
1.269 + {
1.270 + TInt ret = 0;
1.271 + switch (iStatus)
1.272 + {
1.273 +#if defined(_DEBUG)
1.274 + case EDirectStatusInitialising:
1.275 + iWsOwner->PPanic(EWservPanicDirectMisuse);
1.276 +#endif
1.277 + case EDirectStatusNone:
1.278 + break;
1.279 + case EDirectStatusRunning:
1.280 + Terminate1();
1.281 + Terminate2();
1.282 + /*Fall through*/
1.283 + case EDirectStatusCanceling:
1.284 + ret = 1;
1.285 + iMsgQueue->Send(RDirectScreenAccess::ETerminateCancel);
1.286 + break;
1.287 + case EDirectStatusAbortedWindow:
1.288 + case EDirectStatusAbortedGlobal:
1.289 + CorrectScreen();
1.290 + break;
1.291 + case EDirectStatusCompleted:
1.292 + break;
1.293 + default:
1.294 + {
1.295 + }
1.296 + }
1.297 + SetReply(ret);
1.298 + iStatus=EDirectStatusNone;
1.299 + }
1.300 +
1.301 +void CWsDirectScreenAccess::Aborted()
1.302 + {
1.303 + switch (iStatus)
1.304 + {
1.305 + case EDirectStatusRunning:
1.306 + Terminate1();
1.307 + Terminate2();
1.308 + iStatus=EDirectStatusCanceling;
1.309 + break;
1.310 + case EDirectStatusAbortedWindow:
1.311 + case EDirectStatusAbortedGlobal:
1.312 + CorrectScreen();
1.313 + /*Fall through*/
1.314 + case EDirectStatusCompleted:
1.315 + iStatus=EDirectStatusNone;
1.316 + break;
1.317 + default:
1.318 + iWsOwner->PPanic(EWservPanicDirectMisuse);
1.319 + }
1.320 + }
1.321 +
1.322 +void CWsDirectScreenAccess::AbortNow()
1.323 + {
1.324 + if (iStatus!=EDirectStatusRunning)
1.325 + {
1.326 + iWsOwner->PPanic(EWservPanicDirectMisuse);
1.327 + }
1.328 + SignalAbort(RDirectScreenAccess::ETerminateRegion);
1.329 + TRequestStatus timerStatus;
1.330 + RTimer& timer=CWsTop::Timer();
1.331 + timer.After(timerStatus,400000); //0.4secs
1.332 + User::WaitForRequest(iMsgQueue->Status(),timerStatus);
1.333 + if (timerStatus!=KRequestPending)
1.334 + {
1.335 + Abort();
1.336 + }
1.337 + else
1.338 + {
1.339 + CancelAbortObject();
1.340 + timer.Cancel();
1.341 + User::WaitForRequest(timerStatus);
1.342 + }
1.343 + }
1.344 +
1.345 +void CWsDirectScreenAccess::SignalAbort(RDirectScreenAccess::TTerminationReasons aReason)
1.346 + {
1.347 + DeleteRegionSyncWatchcat();
1.348 +
1.349 + iAbortReason=aReason;
1.350 + if (iStatus==EDirectStatusAbortedWindow)
1.351 + {
1.352 + WS_ASSERT_DEBUG(iAbortReason>RDirectScreenAccess::ETerminateRegion, EWsPanicDirectScreenAccess);
1.353 + Terminate2();
1.354 + return;
1.355 + }
1.356 + if (iStatus!=EDirectStatusRunning)
1.357 + {
1.358 + iWsOwner->PPanic(EWservPanicDirectMisuse);
1.359 + }
1.360 + if (RDirectScreenAccess::ETerminateCancel != aReason)
1.361 + {
1.362 + TInt err;
1.363 + TRAP(err, iRegionSync = CWsDirectScreenAccess::CDSARegionSyncTimer::NewL( *this ) );
1.364 + if ( KErrNone == err )
1.365 + {
1.366 + iFrozenRegion.Copy( iVisible );
1.367 + Screen()->DSARegionSyncStart( *this );
1.368 + }
1.369 + }
1.370 + iMsgQueue->Send(aReason);
1.371 + }
1.372 +
1.373 +void CWsDirectScreenAccess::CancelAbortObject()
1.374 + {
1.375 + iMsgQueue->Complete();
1.376 + iMsgQueue->Cancel();
1.377 + iStatus=EDirectStatusNone;
1.378 + Terminate1();
1.379 + Terminate2();
1.380 + }
1.381 +
1.382 +void CWsDirectScreenAccess::Abort()
1.383 + {
1.384 + if ( iStatus == EDirectStatusRunning )
1.385 + {
1.386 + Terminate1();
1.387 + if (iMsgQueue->Status()==KRequestPending)
1.388 + iStatus=(iAbortReason<=RDirectScreenAccess::ETerminateRegion ? EDirectStatusAbortedWindow:EDirectStatusAbortedGlobal);
1.389 + else
1.390 + iStatus=EDirectStatusCompleted;
1.391 + if (iStatus!=EDirectStatusAbortedWindow)
1.392 + Terminate2();
1.393 + }
1.394 + }
1.395 +
1.396 +
1.397 +TInt CWsDirectScreenAccess::GetSendQueue()
1.398 + {
1.399 + TInt ret = iMsgQueue->CreateSendQueue();
1.400 + if(ret == KErrNone)
1.401 + {
1.402 + iWsOwner->SetResponseHandle(iMsgQueue->SendQueue());
1.403 + }
1.404 + return ret;
1.405 + }
1.406 +
1.407 +TInt CWsDirectScreenAccess::GetRecQueue()
1.408 + {
1.409 + TInt ret = iMsgQueue->CreateRecQueue();
1.410 + if(ret == KErrNone)
1.411 + {
1.412 + iWsOwner->SetResponseHandle(iMsgQueue->RecQueue());
1.413 + }
1.414 + return ret;
1.415 + }
1.416 +
1.417 +
1.418 +void CWsDirectScreenAccess::CommandL(TInt aOpcode,const TAny* aCmdData)
1.419 + {
1.420 + TWsDirectCmdUnion pData;
1.421 + pData.any=aCmdData;
1.422 + switch(aOpcode)
1.423 + {
1.424 + case EWsDirectOpFree:
1.425 + delete this;
1.426 + break;
1.427 + case EWsDirectOpRequest:
1.428 + Request(*pData.Int);
1.429 + break;
1.430 + case EWsDirectOpInitFailed:
1.431 + #if defined(_DEBUG)
1.432 + if (iStatus!=EDirectStatusInitialising)
1.433 + {
1.434 + iWsOwner->PPanic(EWservPanicDirectMisuse);
1.435 + }
1.436 + #endif
1.437 + iStatus=EDirectStatusNone;
1.438 + break;
1.439 + case EWsDirectOpGetRegion:
1.440 + GetRegion(*pData.Int);
1.441 + break;
1.442 + case EWsDirectOpCancel:
1.443 + Cancel();
1.444 + break;
1.445 + case EWsDirectOpGetSendQueue:
1.446 + GetSendQueue();
1.447 + break;
1.448 + case EWsDirectOpGetRecQueue:
1.449 + GetRecQueue();
1.450 + break;
1.451 + default:
1.452 + OwnerPanic(EWservPanicOpcode);
1.453 + break;
1.454 + }
1.455 + }
1.456 +
1.457 +void CWsDirectScreenAccess::Initiate()
1.458 + {
1.459 + iWin->AddDSA(*this);
1.460 + iScreen->AddDirect(*this);
1.461 + if ( IsSyncTimeoutPending() )
1.462 + {
1.463 + Screen()->DSARegionSyncOver( *this );
1.464 +
1.465 + RRegion deltaRgn;
1.466 + deltaRgn.Copy( iFrozenRegion );
1.467 +
1.468 + deltaRgn.SubRegion( iVisible );
1.469 + deltaRgn.Tidy();
1.470 +
1.471 + if ( !deltaRgn.IsEmpty() )
1.472 + {
1.473 + Screen()->ScheduleRegionUpdate( &deltaRgn );
1.474 + }
1.475 +
1.476 + deltaRgn.Close();
1.477 + iFrozenRegion.Clear();
1.478 +
1.479 + DeleteRegionSyncWatchcat();
1.480 + }
1.481 + }
1.482 +TBool CWsDirectScreenAccess::IsAbortRequired(const TRegion& aTopVisibleRegion) const
1.483 + {
1.484 + return ( iStatus == EDirectStatusRunning ) && !RegionsMatch(aTopVisibleRegion, iVisible);
1.485 + }
1.486 +
1.487 +void CWsDirectScreenAccess::Terminate1()
1.488 + {
1.489 + WS_ASSERT_DEBUG(!iWin->DSAs().IsEmpty(), EWsPanicDirectScreenAccess);
1.490 + iWin->RemoveDSA(*this);
1.491 + }
1.492 +
1.493 +void CWsDirectScreenAccess::Terminate2()
1.494 + {
1.495 + iScreen->RemoveDirect(*this);
1.496 + WS_ASSERT_DEBUG(!OnQueue(), EWsPanicDirectScreenAccess);
1.497 + }
1.498 +
1.499 +void CWsDirectScreenAccess::CorrectScreen()
1.500 + {
1.501 + if (iAbortReason<=RDirectScreenAccess::ETerminateRegion)
1.502 + {
1.503 + Terminate2();
1.504 + RootWindow()->Invalidate(&iVisible);
1.505 + }
1.506 + else
1.507 + RootWindow()->InvalidateWholeScreen();
1.508 +
1.509 + WS_ASSERT_DEBUG(!OnQueue(), EWsPanicDirectScreenAccess);
1.510 + }
1.511 +
1.512 +
1.513 +
1.514 +#if defined(_DEBUG)
1.515 +TBool CWsDirectScreenAccess::OnQueue()
1.516 + {
1.517 + return iScreen->IsDirectOnQueue(this);
1.518 + }
1.519 +#endif
1.520 +
1.521 +
1.522 +TBool CWsDirectScreenAccess::IsSyncTimeoutPending() const
1.523 + {
1.524 + TBool res;
1.525 + res = ( NULL != iRegionSync ) && ( iRegionSync->IsActive() );
1.526 + return res;
1.527 + }
1.528 +
1.529 +void CWsDirectScreenAccess::CancelFrozenRegion()
1.530 + {
1.531 + if ( !iFrozenRegion.IsEmpty() )
1.532 + {
1.533 + Screen()->DSARegionSyncOver( *this );
1.534 + Screen()->ScheduleRegionUpdate( &iFrozenRegion );
1.535 + iFrozenRegion.Clear();
1.536 + }
1.537 + }
1.538 +
1.539 +void CWsDirectScreenAccess::DeleteRegionSyncWatchcat()
1.540 + {
1.541 + if ( NULL != iRegionSync )
1.542 + {
1.543 + if ( iRegionSync->IsActive() )
1.544 + {
1.545 + iRegionSync->Cancel();
1.546 + }
1.547 + delete iRegionSync;
1.548 + iRegionSync = NULL;
1.549 + }
1.550 + CancelFrozenRegion();
1.551 + }
1.552 +
1.553 +void CWsDirectScreenAccess::RegionSyncTimeout()
1.554 + {
1.555 + CancelFrozenRegion();
1.556 + }
1.557 +
1.558 +CWsDirectScreenAccess::CDSARegionSyncTimer* CWsDirectScreenAccess::CDSARegionSyncTimer::NewL(CWsDirectScreenAccess& aDSA)
1.559 + {
1.560 + CWsDirectScreenAccess::CDSARegionSyncTimer* self = new ( ELeave ) CWsDirectScreenAccess::CDSARegionSyncTimer( aDSA );
1.561 +
1.562 + CleanupStack::PushL( self );
1.563 + self->ConstructL();
1.564 + CleanupStack::Pop( self );
1.565 +
1.566 + CActiveScheduler::Add( self );
1.567 + self->After( TTimeIntervalMicroSeconds32( KRegionSyncTimeoutMicrosec ) );
1.568 + return self;
1.569 + }
1.570 +
1.571 +void CWsDirectScreenAccess::CDSARegionSyncTimer::RunL()
1.572 + {
1.573 + iDSA.RegionSyncTimeout();
1.574 + }
1.575 +
1.576 +CWsDirectScreenAccess::CDSARegionSyncTimer::CDSARegionSyncTimer(CWsDirectScreenAccess& aDSA):
1.577 + CTimer( CActive::EPriorityHigh ),
1.578 + iDSA( aDSA )
1.579 + { } // empty
1.580 +
1.581 +
1.582 +static TBool RegionsMatch(const TRegion & aOne, const TRegion & aTwo)
1.583 + {
1.584 + // Check if the regions have equal areas.
1.585 + const TRect* rect1 = aOne.RectangleList();
1.586 + TUint area1 = 0;
1.587 + for(TInt i = 0; i < aOne.Count(); ++i)
1.588 + {
1.589 + area1 += (rect1->Width() * rect1->Height());
1.590 + rect1++;
1.591 + }
1.592 +
1.593 + const TRect* rect2 = aTwo.RectangleList();
1.594 + TUint area2 = 0;
1.595 + for(TInt i = 0; i < aTwo.Count(); ++i)
1.596 + {
1.597 + area2 += (rect2->Width() * rect2->Height());
1.598 + rect2++;
1.599 + }
1.600 +
1.601 + if(area1 != area2)
1.602 + {
1.603 + return EFalse;
1.604 + }
1.605 +
1.606 + // Check if one region is completely contained within the other.
1.607 + STACK_REGION tempRegion;
1.608 + tempRegion.Copy(aOne);
1.609 + tempRegion.SubRegion(aTwo);
1.610 +
1.611 + const TBool ret(tempRegion.IsEmpty());
1.612 + tempRegion.Close();
1.613 +
1.614 + return ret;
1.615 + }
1.616 +