|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "tdirectgdieglcontent_server.h" |
|
17 #include "tdirectgdieglcontent_cube.h" |
|
18 #include "tdirectgdieglcontent_clientserver.h" |
|
19 #include "tdisplaymode_mapping.h" |
|
20 #include <e32debug.h> |
|
21 #include <fbs.h> |
|
22 #include <graphics/sgimage_sw.h> |
|
23 |
|
24 /** |
|
25 Static constructor. |
|
26 */ |
|
27 CEglContent* CEglContent::NewL() |
|
28 { |
|
29 CEglContent* self = NewLC(); |
|
30 CleanupStack::Pop(self); |
|
31 return self; |
|
32 } |
|
33 |
|
34 CEglContent* CEglContent::NewLC() |
|
35 { |
|
36 CEglContent* self = new(ELeave) CEglContent(); |
|
37 CleanupStack::PushL(self); |
|
38 self->ConstructL(); |
|
39 return self; |
|
40 } |
|
41 |
|
42 /** |
|
43 1st phase constructor |
|
44 */ |
|
45 CEglContent::CEglContent() : CTimer(CActive::EPriorityStandard), iMode(ESync) |
|
46 { |
|
47 CActiveScheduler::Add(this); |
|
48 } |
|
49 |
|
50 /** |
|
51 2nd phase constructor |
|
52 */ |
|
53 void CEglContent::ConstructL() |
|
54 { |
|
55 CTimer::ConstructL(); |
|
56 |
|
57 iCube = CGLCube::NewL(EUidPixelFormatXRGB_8888, TSize(200, 200)); |
|
58 } |
|
59 |
|
60 /** |
|
61 Destructor |
|
62 */ |
|
63 CEglContent::~CEglContent() |
|
64 { |
|
65 Cancel(); |
|
66 |
|
67 delete iCube; |
|
68 } |
|
69 |
|
70 /** |
|
71 Handles an active object's request completion event. |
|
72 */ |
|
73 void CEglContent::RunL() |
|
74 { |
|
75 if(iStatus.Int() == KErrNone) |
|
76 { |
|
77 RenderNextFrame(); |
|
78 iFrame = iFrame % KEglContentAsyncMaxFrames; |
|
79 |
|
80 if(iMode == EAsync) |
|
81 { |
|
82 // issue request for next frame |
|
83 After(KEglContentDelay); |
|
84 } |
|
85 } |
|
86 } |
|
87 |
|
88 /** |
|
89 Render next frame of animation. |
|
90 Function returns when rendering is finished. Animation is set to next frame. |
|
91 */ |
|
92 void CEglContent::RenderNextFrame() |
|
93 { |
|
94 iCube->Render(iFrame); |
|
95 iLastFrame = iFrame; |
|
96 iFrame++; |
|
97 } |
|
98 |
|
99 /** |
|
100 Set rendering mode to synchronous or asynchronous |
|
101 @param aMode Rendering mode to set. |
|
102 */ |
|
103 void CEglContent::SetMode(TMode aMode) |
|
104 { |
|
105 if(aMode == iMode) |
|
106 return; |
|
107 |
|
108 iMode = aMode; |
|
109 |
|
110 // reset mode |
|
111 if(aMode == ESync) |
|
112 { |
|
113 // cancel request for next frame |
|
114 Cancel(); |
|
115 iFrame = 0; |
|
116 } |
|
117 else if(aMode == EAsync) |
|
118 { |
|
119 // render init frame |
|
120 iFrame = 0; |
|
121 RenderNextFrame(); |
|
122 // issue request for next frame |
|
123 After(KEglContentDelay); |
|
124 } |
|
125 else // EAsyncDebug |
|
126 { |
|
127 // render init frame |
|
128 iFrame = 0; |
|
129 RenderNextFrame(); |
|
130 } |
|
131 } |
|
132 |
|
133 /** |
|
134 Get image id of current frame. Current image to render is switch to next. |
|
135 @param aId Reference to drawable id class to store image id. |
|
136 @return number of frame stored in image |
|
137 */ |
|
138 TInt CEglContent::GetImage(TSgDrawableId& aId) |
|
139 { |
|
140 if(iMode == ESync) |
|
141 { |
|
142 // if rendering mode is synchrounous, we need to render current frame |
|
143 RenderNextFrame(); |
|
144 } |
|
145 |
|
146 iCube->GetImage(aId); |
|
147 |
|
148 if(iMode == EAsyncDebug) |
|
149 { |
|
150 // Added this as a panic can occur if After() is called while the server is active. |
|
151 // Before this was added the server could get stuck in an active state |
|
152 // occasionally when running the tests in SW mode. |
|
153 if (IsActive()) |
|
154 Cancel(); |
|
155 |
|
156 // if rendering mode is asynchrounous debug, we start rendering next frame (only one) immediately |
|
157 After(0); |
|
158 } |
|
159 |
|
160 return iLastFrame; |
|
161 } |
|
162 |
|
163 /** |
|
164 Static constructor |
|
165 */ |
|
166 CServer2* CEglContentServer::NewLC() |
|
167 { |
|
168 CEglContentServer* self = new(ELeave) CEglContentServer; |
|
169 CleanupStack::PushL(self); |
|
170 self->ConstructL(); |
|
171 return self; |
|
172 } |
|
173 |
|
174 /** |
|
175 1st phase constructor |
|
176 */ |
|
177 CEglContentServer::CEglContentServer() : CServer2(0, ESharableSessions) |
|
178 { |
|
179 } |
|
180 |
|
181 /** |
|
182 2nd phase construction - ensure the content renderer and server objects are running |
|
183 */ |
|
184 void CEglContentServer::ConstructL() |
|
185 { |
|
186 StartL(KEglContentServerName); |
|
187 iContent = CEglContent::NewL(); |
|
188 } |
|
189 |
|
190 /** |
|
191 Destructor. |
|
192 */ |
|
193 CEglContentServer::~CEglContentServer() |
|
194 { |
|
195 delete iContent; |
|
196 } |
|
197 |
|
198 /** |
|
199 Cretae a new client session. |
|
200 */ |
|
201 CSession2* CEglContentServer::NewSessionL(const TVersion&, const RMessage2&) const |
|
202 { |
|
203 return new(ELeave) CEglContentSession(); |
|
204 } |
|
205 |
|
206 /* |
|
207 A new session is being created |
|
208 */ |
|
209 void CEglContentServer::AddSession() |
|
210 { |
|
211 ++iSessionCount; |
|
212 } |
|
213 |
|
214 /* |
|
215 A session is being destroyed |
|
216 */ |
|
217 void CEglContentServer::DropSession() |
|
218 { |
|
219 --iSessionCount; |
|
220 } |
|
221 |
|
222 /** |
|
223 Get image in synchronous mode. |
|
224 @param aId Reference to drawable id class to store image id. |
|
225 */ |
|
226 void CEglContentServer::GetSyncImage(TSgDrawableId& aId) |
|
227 { |
|
228 if(iContent) |
|
229 { |
|
230 iContent->SetMode(CEglContent::ESync); |
|
231 iContent->GetImage(aId); |
|
232 } |
|
233 } |
|
234 |
|
235 /** |
|
236 Get image in asynchronous mode. |
|
237 @param aId Reference to drawable id class to store image id. |
|
238 @return number of frame stored in image |
|
239 */ |
|
240 TInt CEglContentServer::GetAsyncImage(TSgDrawableId& aId) |
|
241 { |
|
242 if(iContent) |
|
243 { |
|
244 iContent->SetMode(CEglContent::EAsync); |
|
245 return iContent->GetImage(aId); |
|
246 } |
|
247 return -1; |
|
248 } |
|
249 |
|
250 /** |
|
251 Get image in asynchronous debug mode. |
|
252 @param aId Reference to drawable id class to store image id. |
|
253 @return number of frame stored in image |
|
254 */ |
|
255 TInt CEglContentServer::GetAsyncImageDebug(TSgDrawableId& aId) |
|
256 { |
|
257 if(iContent) |
|
258 { |
|
259 iContent->SetMode(CEglContent::EAsyncDebug); |
|
260 return iContent->GetImage(aId); |
|
261 } |
|
262 return -1; |
|
263 } |
|
264 |
|
265 /** |
|
266 1st phase constructor |
|
267 */ |
|
268 CEglContentSession::CEglContentSession() |
|
269 { |
|
270 } |
|
271 |
|
272 /** |
|
273 2nd phase construct for sessions - called by the CServer framework |
|
274 */ |
|
275 void CEglContentSession::Create() |
|
276 { |
|
277 Server().AddSession(); |
|
278 } |
|
279 |
|
280 /** |
|
281 Destructor. |
|
282 */ |
|
283 CEglContentSession::~CEglContentSession() |
|
284 { |
|
285 Server().DropSession(); |
|
286 } |
|
287 |
|
288 /** |
|
289 Get server object. |
|
290 @return a reference to server object |
|
291 */ |
|
292 CEglContentServer& CEglContentSession::Server() |
|
293 { |
|
294 return *static_cast<CEglContentServer*>(const_cast<CServer2*>(CSession2::Server())); |
|
295 } |
|
296 |
|
297 /** |
|
298 Handle a client request. |
|
299 Leaving is handled by CEglContentSession::ServiceError() which reports |
|
300 the error code to the client |
|
301 */ |
|
302 void CEglContentSession::ServiceL(const RMessage2& aMessage) |
|
303 { |
|
304 switch(aMessage.Function()) |
|
305 { |
|
306 case ETerminateServer: |
|
307 { |
|
308 aMessage.Complete(KErrNone); |
|
309 CActiveScheduler::Stop(); |
|
310 break; |
|
311 } |
|
312 case EGetSyncImage: |
|
313 { |
|
314 // Get the current image synchronously, the frame |
|
315 // number is not returned as the client will already know the frame number |
|
316 // as it controls when a frame is drawn |
|
317 TSgDrawableId id; |
|
318 Server().GetSyncImage(id); |
|
319 TPckg<TSgDrawableId> idPckg(id); |
|
320 aMessage.Write(0, idPckg); |
|
321 aMessage.Complete(KErrNone); |
|
322 break; |
|
323 } |
|
324 case EGetAsyncImage: |
|
325 { |
|
326 // Get the current image and it's frame number, the drawing is |
|
327 // asynchronous so the client needs to know which one this as it cannot tell otherwise |
|
328 TSgDrawableId id; |
|
329 TInt fnum = Server().GetAsyncImage(id); |
|
330 TPckg<TSgDrawableId> idPckg(id); |
|
331 aMessage.Write(0, idPckg); |
|
332 TPckg<TInt> fnumPckg(fnum); |
|
333 aMessage.Write(1, fnumPckg); |
|
334 aMessage.Complete(KErrNone); |
|
335 break; |
|
336 } |
|
337 case EGetAsyncImageDebug: |
|
338 { |
|
339 // Get the current image and it's frame number, the drawing is |
|
340 // asynchronous so the client needs to know which one this as it cannot tell otherwise |
|
341 TSgDrawableId id; |
|
342 TInt fnum = Server().GetAsyncImageDebug(id); |
|
343 TPckg<TSgDrawableId> idPckg(id); |
|
344 aMessage.Write(0, idPckg); |
|
345 TPckg<TInt> fnumPckg(fnum); |
|
346 aMessage.Write(1, fnumPckg); |
|
347 aMessage.Complete(KErrNone); |
|
348 break; |
|
349 } |
|
350 default: |
|
351 { |
|
352 PanicClient(aMessage, EPanicIllegalFunction); |
|
353 } |
|
354 } |
|
355 } |
|
356 |
|
357 /** |
|
358 Handle an error from CEglContentSession::ServiceL() |
|
359 */ |
|
360 void CEglContentSession::ServiceError(const RMessage2& aMessage, TInt aError) |
|
361 { |
|
362 if(aError == KErrBadDescriptor) |
|
363 PanicClient(aMessage, EPanicBadDescriptor); |
|
364 CSession2::ServiceError(aMessage, aError); |
|
365 } |
|
366 |
|
367 |
|
368 /** |
|
369 RMessage::Panic() also completes the message. |
|
370 */ |
|
371 void PanicClient(const RMessagePtr2& aMessage, TEglContentPanic aPanic) |
|
372 { |
|
373 aMessage.Panic(KEglContentServerName, aPanic); |
|
374 } |
|
375 |
|
376 /** |
|
377 Perform all server initialisation, in particular creation of the |
|
378 scheduler and server and then run the scheduler |
|
379 */ |
|
380 static void RunServerL() |
|
381 { |
|
382 // naming the server thread after the server helps to debug panics |
|
383 User::LeaveIfError(RThread::RenameMe(KEglContentServerName)); |
|
384 // |
|
385 // create and install the active scheduler we need |
|
386 CActiveScheduler* s = new(ELeave) CActiveScheduler; |
|
387 CleanupStack::PushL(s); |
|
388 CActiveScheduler::Install(s); |
|
389 // |
|
390 // create the server (leave it on the cleanup stack) |
|
391 CEglContentServer::NewLC(); |
|
392 // |
|
393 // Initialisation complete, now signal the client |
|
394 RProcess::Rendezvous(KErrNone); |
|
395 // |
|
396 // Ready to run |
|
397 CActiveScheduler::Start(); |
|
398 // |
|
399 // Cleanup the server and scheduler |
|
400 CleanupStack::PopAndDestroy(2); |
|
401 } |
|
402 |
|
403 /** |
|
404 Entry point of server executable. |
|
405 */ |
|
406 GLDEF_C TInt E32Main() |
|
407 { |
|
408 __UHEAP_MARK; |
|
409 RDebug::Print(_L("%S started"), &KEglContentServerName); |
|
410 CTrapCleanup* cleanup = CTrapCleanup::New(); |
|
411 TInt r = KErrNoMemory; |
|
412 if(cleanup) |
|
413 { |
|
414 TRAP(r, RunServerL()); |
|
415 delete cleanup; |
|
416 } |
|
417 RDebug::Print(_L("%S terminated"), &KEglContentServerName); |
|
418 __UHEAP_MARKEND; |
|
419 return r; |
|
420 } |