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