sl@0: // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "tdirectgdieglcontent_server.h" sl@0: #include "tdirectgdieglcontent_cube.h" sl@0: #include "tdirectgdieglcontent_clientserver.h" sl@0: #include "tdisplaymode_mapping.h" sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: /** sl@0: Static constructor. sl@0: */ sl@0: CEglContent* CEglContent::NewL() sl@0: { sl@0: CEglContent* self = NewLC(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CEglContent* CEglContent::NewLC() sl@0: { sl@0: CEglContent* self = new(ELeave) CEglContent(); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: return self; sl@0: } sl@0: sl@0: /** sl@0: 1st phase constructor sl@0: */ sl@0: CEglContent::CEglContent() : CTimer(CActive::EPriorityStandard), iMode(ESync) sl@0: { sl@0: CActiveScheduler::Add(this); sl@0: } sl@0: sl@0: /** sl@0: 2nd phase constructor sl@0: */ sl@0: void CEglContent::ConstructL() sl@0: { sl@0: CTimer::ConstructL(); sl@0: sl@0: iCube = CGLCube::NewL(EUidPixelFormatXRGB_8888, TSize(200, 200)); sl@0: } sl@0: sl@0: /** sl@0: Destructor sl@0: */ sl@0: CEglContent::~CEglContent() sl@0: { sl@0: Cancel(); sl@0: sl@0: delete iCube; sl@0: } sl@0: sl@0: /** sl@0: Handles an active object's request completion event. sl@0: */ sl@0: void CEglContent::RunL() sl@0: { sl@0: if(iStatus.Int() == KErrNone) sl@0: { sl@0: RenderNextFrame(); sl@0: iFrame = iFrame % KEglContentAsyncMaxFrames; sl@0: sl@0: if(iMode == EAsync) sl@0: { sl@0: // issue request for next frame sl@0: After(KEglContentDelay); sl@0: } sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Render next frame of animation. sl@0: Function returns when rendering is finished. Animation is set to next frame. sl@0: */ sl@0: void CEglContent::RenderNextFrame() sl@0: { sl@0: iCube->Render(iFrame); sl@0: iLastFrame = iFrame; sl@0: iFrame++; sl@0: } sl@0: sl@0: /** sl@0: Set rendering mode to synchronous or asynchronous sl@0: @param aMode Rendering mode to set. sl@0: */ sl@0: void CEglContent::SetMode(TMode aMode) sl@0: { sl@0: if(aMode == iMode) sl@0: return; sl@0: sl@0: iMode = aMode; sl@0: sl@0: // reset mode sl@0: if(aMode == ESync) sl@0: { sl@0: // cancel request for next frame sl@0: Cancel(); sl@0: iFrame = 0; sl@0: } sl@0: else if(aMode == EAsync) sl@0: { sl@0: // render init frame sl@0: iFrame = 0; sl@0: RenderNextFrame(); sl@0: // issue request for next frame sl@0: After(KEglContentDelay); sl@0: } sl@0: else // EAsyncDebug sl@0: { sl@0: // render init frame sl@0: iFrame = 0; sl@0: RenderNextFrame(); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Get image id of current frame. Current image to render is switch to next. sl@0: @param aId Reference to drawable id class to store image id. sl@0: @return number of frame stored in image sl@0: */ sl@0: TInt CEglContent::GetImage(TSgDrawableId& aId) sl@0: { sl@0: if(iMode == ESync) sl@0: { sl@0: // if rendering mode is synchrounous, we need to render current frame sl@0: RenderNextFrame(); sl@0: } sl@0: sl@0: iCube->GetImage(aId); sl@0: sl@0: if(iMode == EAsyncDebug) sl@0: { sl@0: // Added this as a panic can occur if After() is called while the server is active. sl@0: // Before this was added the server could get stuck in an active state sl@0: // occasionally when running the tests in SW mode. sl@0: if (IsActive()) sl@0: Cancel(); sl@0: sl@0: // if rendering mode is asynchrounous debug, we start rendering next frame (only one) immediately sl@0: After(0); sl@0: } sl@0: sl@0: return iLastFrame; sl@0: } sl@0: sl@0: /** sl@0: Static constructor sl@0: */ sl@0: CServer2* CEglContentServer::NewLC() sl@0: { sl@0: CEglContentServer* self = new(ELeave) CEglContentServer; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: return self; sl@0: } sl@0: sl@0: /** sl@0: 1st phase constructor sl@0: */ sl@0: CEglContentServer::CEglContentServer() : CServer2(0, ESharableSessions) sl@0: { sl@0: } sl@0: sl@0: /** sl@0: 2nd phase construction - ensure the content renderer and server objects are running sl@0: */ sl@0: void CEglContentServer::ConstructL() sl@0: { sl@0: StartL(KEglContentServerName); sl@0: iContent = CEglContent::NewL(); sl@0: } sl@0: sl@0: /** sl@0: Destructor. sl@0: */ sl@0: CEglContentServer::~CEglContentServer() sl@0: { sl@0: delete iContent; sl@0: } sl@0: sl@0: /** sl@0: Cretae a new client session. sl@0: */ sl@0: CSession2* CEglContentServer::NewSessionL(const TVersion&, const RMessage2&) const sl@0: { sl@0: return new(ELeave) CEglContentSession(); sl@0: } sl@0: sl@0: /* sl@0: A new session is being created sl@0: */ sl@0: void CEglContentServer::AddSession() sl@0: { sl@0: ++iSessionCount; sl@0: } sl@0: sl@0: /* sl@0: A session is being destroyed sl@0: */ sl@0: void CEglContentServer::DropSession() sl@0: { sl@0: --iSessionCount; sl@0: } sl@0: sl@0: /** sl@0: Get image in synchronous mode. sl@0: @param aId Reference to drawable id class to store image id. sl@0: */ sl@0: void CEglContentServer::GetSyncImage(TSgDrawableId& aId) sl@0: { sl@0: if(iContent) sl@0: { sl@0: iContent->SetMode(CEglContent::ESync); sl@0: iContent->GetImage(aId); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Get image in asynchronous mode. sl@0: @param aId Reference to drawable id class to store image id. sl@0: @return number of frame stored in image sl@0: */ sl@0: TInt CEglContentServer::GetAsyncImage(TSgDrawableId& aId) sl@0: { sl@0: if(iContent) sl@0: { sl@0: iContent->SetMode(CEglContent::EAsync); sl@0: return iContent->GetImage(aId); sl@0: } sl@0: return -1; sl@0: } sl@0: sl@0: /** sl@0: Get image in asynchronous debug mode. sl@0: @param aId Reference to drawable id class to store image id. sl@0: @return number of frame stored in image sl@0: */ sl@0: TInt CEglContentServer::GetAsyncImageDebug(TSgDrawableId& aId) sl@0: { sl@0: if(iContent) sl@0: { sl@0: iContent->SetMode(CEglContent::EAsyncDebug); sl@0: return iContent->GetImage(aId); sl@0: } sl@0: return -1; sl@0: } sl@0: sl@0: /** sl@0: 1st phase constructor sl@0: */ sl@0: CEglContentSession::CEglContentSession() sl@0: { sl@0: } sl@0: sl@0: /** sl@0: 2nd phase construct for sessions - called by the CServer framework sl@0: */ sl@0: void CEglContentSession::Create() sl@0: { sl@0: Server().AddSession(); sl@0: } sl@0: sl@0: /** sl@0: Destructor. sl@0: */ sl@0: CEglContentSession::~CEglContentSession() sl@0: { sl@0: Server().DropSession(); sl@0: } sl@0: sl@0: /** sl@0: Get server object. sl@0: @return a reference to server object sl@0: */ sl@0: CEglContentServer& CEglContentSession::Server() sl@0: { sl@0: return *static_cast(const_cast(CSession2::Server())); sl@0: } sl@0: sl@0: /** sl@0: Handle a client request. sl@0: Leaving is handled by CEglContentSession::ServiceError() which reports sl@0: the error code to the client sl@0: */ sl@0: void CEglContentSession::ServiceL(const RMessage2& aMessage) sl@0: { sl@0: switch(aMessage.Function()) sl@0: { sl@0: case ETerminateServer: sl@0: { sl@0: aMessage.Complete(KErrNone); sl@0: CActiveScheduler::Stop(); sl@0: break; sl@0: } sl@0: case EGetSyncImage: sl@0: { sl@0: // Get the current image synchronously, the frame sl@0: // number is not returned as the client will already know the frame number sl@0: // as it controls when a frame is drawn sl@0: TSgDrawableId id; sl@0: Server().GetSyncImage(id); sl@0: TPckg idPckg(id); sl@0: aMessage.Write(0, idPckg); sl@0: aMessage.Complete(KErrNone); sl@0: break; sl@0: } sl@0: case EGetAsyncImage: sl@0: { sl@0: // Get the current image and it's frame number, the drawing is sl@0: // asynchronous so the client needs to know which one this as it cannot tell otherwise sl@0: TSgDrawableId id; sl@0: TInt fnum = Server().GetAsyncImage(id); sl@0: TPckg idPckg(id); sl@0: aMessage.Write(0, idPckg); sl@0: TPckg fnumPckg(fnum); sl@0: aMessage.Write(1, fnumPckg); sl@0: aMessage.Complete(KErrNone); sl@0: break; sl@0: } sl@0: case EGetAsyncImageDebug: sl@0: { sl@0: // Get the current image and it's frame number, the drawing is sl@0: // asynchronous so the client needs to know which one this as it cannot tell otherwise sl@0: TSgDrawableId id; sl@0: TInt fnum = Server().GetAsyncImageDebug(id); sl@0: TPckg idPckg(id); sl@0: aMessage.Write(0, idPckg); sl@0: TPckg fnumPckg(fnum); sl@0: aMessage.Write(1, fnumPckg); sl@0: aMessage.Complete(KErrNone); sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: PanicClient(aMessage, EPanicIllegalFunction); sl@0: } sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Handle an error from CEglContentSession::ServiceL() sl@0: */ sl@0: void CEglContentSession::ServiceError(const RMessage2& aMessage, TInt aError) sl@0: { sl@0: if(aError == KErrBadDescriptor) sl@0: PanicClient(aMessage, EPanicBadDescriptor); sl@0: CSession2::ServiceError(aMessage, aError); sl@0: } sl@0: sl@0: sl@0: /** sl@0: RMessage::Panic() also completes the message. sl@0: */ sl@0: void PanicClient(const RMessagePtr2& aMessage, TEglContentPanic aPanic) sl@0: { sl@0: aMessage.Panic(KEglContentServerName, aPanic); sl@0: } sl@0: sl@0: /** sl@0: Perform all server initialisation, in particular creation of the sl@0: scheduler and server and then run the scheduler sl@0: */ sl@0: static void RunServerL() sl@0: { sl@0: // naming the server thread after the server helps to debug panics sl@0: User::LeaveIfError(RThread::RenameMe(KEglContentServerName)); sl@0: // sl@0: // create and install the active scheduler we need sl@0: CActiveScheduler* s = new(ELeave) CActiveScheduler; sl@0: CleanupStack::PushL(s); sl@0: CActiveScheduler::Install(s); sl@0: // sl@0: // create the server (leave it on the cleanup stack) sl@0: CEglContentServer::NewLC(); sl@0: // sl@0: // Initialisation complete, now signal the client sl@0: RProcess::Rendezvous(KErrNone); sl@0: // sl@0: // Ready to run sl@0: CActiveScheduler::Start(); sl@0: // sl@0: // Cleanup the server and scheduler sl@0: CleanupStack::PopAndDestroy(2); sl@0: } sl@0: sl@0: /** sl@0: Entry point of server executable. sl@0: */ sl@0: GLDEF_C TInt E32Main() sl@0: { sl@0: __UHEAP_MARK; sl@0: RDebug::Print(_L("%S started"), &KEglContentServerName); sl@0: CTrapCleanup* cleanup = CTrapCleanup::New(); sl@0: TInt r = KErrNoMemory; sl@0: if(cleanup) sl@0: { sl@0: TRAP(r, RunServerL()); sl@0: delete cleanup; sl@0: } sl@0: RDebug::Print(_L("%S terminated"), &KEglContentServerName); sl@0: __UHEAP_MARKEND; sl@0: return r; sl@0: }