|
1 // Copyright (c) 2006-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 /** |
|
17 @file |
|
18 @test |
|
19 @internalComponent - Internal Symbian test code |
|
20 */ |
|
21 |
|
22 #include "redirector.h" |
|
23 #include <fbs.h> |
|
24 #include <bitdev.h> |
|
25 #include <bitstd.h> |
|
26 #include <gdi.h> |
|
27 #ifdef __WINS__ |
|
28 #include "../debuglog/osbwin.h" |
|
29 #endif |
|
30 |
|
31 const TInt KDefaultScreen = 0; |
|
32 |
|
33 const TUint8 KCmdQuery = 0; |
|
34 const TUint8 KCmdSetGcFront = 1; |
|
35 const TUint8 KCmdSetGcBack = 2; |
|
36 const TUint8 KCmdResetGcFront = 3; |
|
37 const TUint8 KCmdResetGcBack = 4; |
|
38 const TUint8 KCmdSetBackObject = 5; |
|
39 const TUint8 KCmdResetBackObject= 6; |
|
40 |
|
41 const TUint8 KRedirectorInfoSig = 0x7e; |
|
42 |
|
43 NONSHARABLE_STRUCT(TRedirectorInfo) |
|
44 { |
|
45 TUint8 iSignature; |
|
46 TAny* iFrontBufferInterface; |
|
47 TAny* iBackBufferInterface; |
|
48 TAny* iScreenConfigInterface; |
|
49 TInt iScreenBitmapHandle; |
|
50 TInt iFlickerBitmapHandle; |
|
51 TInt iUpdateCounter; |
|
52 }; |
|
53 |
|
54 NONSHARABLE_STRUCT(TWsBackBuffer): public MWsBackBuffer |
|
55 { |
|
56 public: |
|
57 TWsBackBuffer(CFbsBitmap* aBit,CFbsBitGc* aGc): iBit(aBit), iGc(aGc) |
|
58 {} |
|
59 virtual CFbsBitmap* GetBitmap() |
|
60 {return iBit;} |
|
61 virtual CFbsBitGc* GetBitGc() |
|
62 {return iGc;} |
|
63 virtual TInt SetBitGc(CFbsBitGc*) |
|
64 {return KErrNotSupported;} |
|
65 virtual TInt RedirectTo(MWsBackBuffer*) |
|
66 {return KErrNotSupported;} |
|
67 virtual void SetObserver(MWsFlickerFreeBufferObserver* /*aObserver*/) |
|
68 {ASSERT(0);} |
|
69 virtual MWsFlickerFreeBufferObserver* Observer() |
|
70 { |
|
71 ASSERT(0); |
|
72 return NULL; |
|
73 } |
|
74 virtual CFbsBitGc* GetBitGcCurrent() |
|
75 { |
|
76 ASSERT(0); |
|
77 return NULL; |
|
78 } |
|
79 |
|
80 private: |
|
81 CFbsBitmap* iBit; |
|
82 CFbsBitGc* iGc; |
|
83 }; |
|
84 |
|
85 // |
|
86 CWsGcRedirector* CWsGcRedirector::NewL() |
|
87 { |
|
88 return new(ELeave) CWsGcRedirector; |
|
89 } |
|
90 |
|
91 CWsGcRedirector::~CWsGcRedirector() |
|
92 { |
|
93 #ifdef __WINS__ |
|
94 delete iFrontWin; |
|
95 delete iBackWin; |
|
96 delete iUpdateDebugWinsTimer; |
|
97 #endif |
|
98 |
|
99 if (iFrontBuf) |
|
100 iFrontBuf->SetBitGc(NULL); |
|
101 if (iBackBuf) |
|
102 iBackBuf->SetBitGc(NULL); |
|
103 |
|
104 delete iFrontGc; |
|
105 delete iFrontDev; |
|
106 delete iFrontBit; |
|
107 delete iBackGc; |
|
108 delete iBackDev; |
|
109 delete iBackBit; |
|
110 delete iBadGc; |
|
111 delete iBackObj; |
|
112 } |
|
113 |
|
114 void CWsGcRedirector::ConstructL(MWsGraphicDrawerEnvironment& aEnv, const TGraphicDrawerId& aId, MWsClient& aOwner, const TDesC8& aData) |
|
115 { |
|
116 BaseConstructL(aEnv, aId, aOwner); |
|
117 |
|
118 #ifdef __WINS__ |
|
119 if (aData.Length()>1) |
|
120 iDisableWin = aData[1]==1; |
|
121 #endif |
|
122 iScreenId = KDefaultScreen; |
|
123 if (aData.Length()>0) |
|
124 iScreenId = aData[0]; |
|
125 MWsScreen* scr = aEnv.Screen(iScreenId); |
|
126 User::LeaveIfNull(scr); |
|
127 |
|
128 MWsScreenConfig* cfg = scr->ObjectInterface<MWsScreenConfig>(); |
|
129 User::LeaveIfNull(cfg); |
|
130 |
|
131 iFrontBuf = scr->ObjectInterface<MWsFrontBuffer>(); |
|
132 User::LeaveIfNull(iFrontBuf); |
|
133 iBackBuf = scr->ObjectInterface<MWsBackBuffer>(); |
|
134 |
|
135 iFrontBit = new(ELeave) CFbsBitmap; |
|
136 iDefaultSize=cfg->SizeInPixels(); |
|
137 User::LeaveIfError(iFrontBit->Create(iDefaultSize,EColor64K)); |
|
138 iFrontDev = CFbsBitmapDevice::NewL(iFrontBit); |
|
139 User::LeaveIfNull(iFrontDev); |
|
140 User::LeaveIfError(iFrontDev->CreateContext(iFrontGc)); |
|
141 |
|
142 User::LeaveIfError(iFrontDev->CreateContext(iBadGc)); |
|
143 iBadGc->ChangeDevice(NULL); |
|
144 |
|
145 #ifdef __WINS__ |
|
146 if (!iDisableWin) |
|
147 { |
|
148 iUpdateDebugWinsTimer = CPeriodic::NewL(0); |
|
149 iUpdateDebugWinsTimer->Start(0, 300 * 1000, TCallBack(UpdateDebugWindowsCallback, this)); |
|
150 |
|
151 _LIT(KRedFront, "RedFront"); |
|
152 iFrontWin = CDebugOsbWin::NewL(KRedFront, iFrontBit->SizeInPixels()); |
|
153 } |
|
154 #endif |
|
155 |
|
156 if (iBackBuf) |
|
157 { |
|
158 CFbsBitmap* bit = iBackBuf->GetBitmap(); |
|
159 User::LeaveIfNull(bit); |
|
160 iBackBit = new(ELeave) CFbsBitmap; |
|
161 User::LeaveIfError(iBackBit->Create(bit->SizeInPixels(),EColor64K)); |
|
162 iBackDev = CFbsBitmapDevice::NewL(iBackBit); |
|
163 User::LeaveIfNull(iBackDev); |
|
164 User::LeaveIfError(iBackDev->CreateContext(iBackGc)); |
|
165 |
|
166 iBackObj = new(ELeave) TWsBackBuffer(iBackBit,iBackGc); |
|
167 #ifdef __WINS__ |
|
168 if (!iDisableWin) |
|
169 { |
|
170 _LIT(KRedBack, "RedBack"); |
|
171 iBackWin = CDebugOsbWin::NewL(KRedBack, iBackBit->SizeInPixels()); |
|
172 } |
|
173 #endif |
|
174 } |
|
175 |
|
176 // compile check, non-const interface access |
|
177 MWsGraphicDrawerEnvironment& ee = Env(); |
|
178 MWsScreen* ss = ee.Screen(iScreenId); |
|
179 MWsScreenConfig* cc = ss->ObjectInterface<MWsScreenConfig>(); |
|
180 } |
|
181 |
|
182 void CWsGcRedirector::HandleMessage(const TDesC8& aData) |
|
183 { |
|
184 // wserv already check data size, and won't invoke this handler if it's empty |
|
185 TBuf8<1> ack; |
|
186 ack.Append(KRedirectorInfoSig); |
|
187 |
|
188 switch (aData[0]) |
|
189 { |
|
190 case KCmdQuery: |
|
191 SendInfo(); |
|
192 break; |
|
193 |
|
194 case KCmdSetGcFront: |
|
195 Env().RegisterEventHandler(this,this,TWservCrEvent::EScreenUpdated|TWservCrEvent::EScreenOrientationChanged|TWservCrEvent::EDeviceOrientationChanged); |
|
196 |
|
197 // -test bad gc |
|
198 __ASSERT_ALWAYS(iFrontBuf->SetBitGc(iBadGc)==KErrArgument, User::Invariant()); |
|
199 // -test bad gc |
|
200 __ASSERT_ALWAYS(iFrontBuf->SetBitGc(iBadGc,ETrue)==KErrArgument, User::Invariant()); |
|
201 // +test |
|
202 __ASSERT_ALWAYS(iFrontBuf->SetBitGc(iFrontGc,EFalse)==KErrNone, User::Invariant()); |
|
203 // -test duplicate calls |
|
204 __ASSERT_ALWAYS(iFrontBuf->SetBitGc(iFrontGc)==KErrAlreadyExists, User::Invariant()); |
|
205 |
|
206 SendMessage(ack); |
|
207 break; |
|
208 |
|
209 case KCmdSetGcBack: |
|
210 if (iBackBuf) |
|
211 { |
|
212 // -test bad gc |
|
213 __ASSERT_ALWAYS(iBackBuf->SetBitGc(iBadGc)==KErrArgument, User::Invariant()); |
|
214 // +test |
|
215 __ASSERT_ALWAYS(iBackBuf->SetBitGc(iBackGc)==KErrNone, User::Invariant()); |
|
216 // -test duplicate calls |
|
217 __ASSERT_ALWAYS(iBackBuf->SetBitGc(iBackGc)==KErrAlreadyExists, User::Invariant()); |
|
218 // -test double redirection |
|
219 __ASSERT_ALWAYS(iBackBuf->RedirectTo(iBackObj)==KErrInUse, User::Invariant()); |
|
220 } |
|
221 SendMessage(ack); |
|
222 break; |
|
223 |
|
224 case KCmdResetGcFront: |
|
225 Env().UnregisterEventHandler(this); |
|
226 iUpdateCounter = 0; |
|
227 |
|
228 __ASSERT_ALWAYS(iFrontBuf->SetBitGc(NULL,EFalse)==KErrNone, User::Invariant()); |
|
229 // -test duplicate calls |
|
230 __ASSERT_ALWAYS(iFrontBuf->SetBitGc(NULL,EFalse)==KErrNone, User::Invariant()); |
|
231 SendMessage(ack); |
|
232 break; |
|
233 |
|
234 case KCmdResetGcBack: |
|
235 if (iBackBuf) |
|
236 { |
|
237 // +test |
|
238 __ASSERT_ALWAYS(iBackBuf->SetBitGc(NULL)==KErrNone, User::Invariant()); |
|
239 // -test duplicate calls |
|
240 __ASSERT_ALWAYS(iBackBuf->SetBitGc(NULL)==KErrNone, User::Invariant()); |
|
241 } |
|
242 SendMessage(ack); |
|
243 break; |
|
244 |
|
245 case KCmdSetBackObject: |
|
246 if (iBackBuf) |
|
247 { |
|
248 TWsBackBuffer badObj1(NULL,iBackGc); |
|
249 // -test bad obj (null bitmap) |
|
250 __ASSERT_ALWAYS(iBackBuf->RedirectTo(&badObj1)==KErrArgument, User::Invariant()); |
|
251 // -test bad obj (null gc) |
|
252 TWsBackBuffer badObj2(iBackBit,NULL); |
|
253 __ASSERT_ALWAYS(iBackBuf->RedirectTo(&badObj2)==KErrArgument, User::Invariant()); |
|
254 // -test bad obj (null device) |
|
255 TWsBackBuffer badObj3(iBackBit,iBadGc); |
|
256 __ASSERT_ALWAYS(iBackBuf->RedirectTo(&badObj3)==KErrArgument, User::Invariant()); |
|
257 // +test |
|
258 __ASSERT_ALWAYS(iBackBuf->RedirectTo(iBackObj)==KErrNone, User::Invariant()); |
|
259 // -test duplicate calls |
|
260 __ASSERT_ALWAYS(iBackBuf->RedirectTo(iBackObj)==KErrAlreadyExists, User::Invariant()); |
|
261 // -test double redirection |
|
262 __ASSERT_ALWAYS(iBackBuf->SetBitGc(iBackGc)==KErrInUse, User::Invariant()); |
|
263 } |
|
264 SendMessage(ack); |
|
265 break; |
|
266 |
|
267 case KCmdResetBackObject: |
|
268 if (iBackBuf) |
|
269 { |
|
270 // +test |
|
271 __ASSERT_ALWAYS(iBackBuf->RedirectTo(NULL)==KErrNone, User::Invariant()); |
|
272 // -test duplicate calls |
|
273 __ASSERT_ALWAYS(iBackBuf->RedirectTo(NULL)==KErrNone, User::Invariant()); |
|
274 } |
|
275 SendMessage(ack); |
|
276 break; |
|
277 } |
|
278 } |
|
279 |
|
280 void CWsGcRedirector::DoDraw(MWsGc& aGc, const TRect& aRect, const TDesC8& aData) const |
|
281 { |
|
282 aGc.PushBitGcSettings(); |
|
283 CFbsBitGc& bc = aGc.BitGc(); |
|
284 bc.SetBrushStyle(CGraphicsContext::ESolidBrush); |
|
285 bc.SetBrushColor(TRgb(255,0,0,128)); |
|
286 bc.DrawRect(aRect); |
|
287 TGraphicDrawerId id; |
|
288 id.iId = 0x10281fb6; |
|
289 id.iIsUid = ETrue; |
|
290 const CWsGraphicDrawer* listener = Env().ResolveGraphic(id); |
|
291 if (listener) |
|
292 listener->Draw(aGc, aRect, aData); |
|
293 aGc.PopBitGcSettings(); |
|
294 |
|
295 // compile check, const interface access |
|
296 const MWsGraphicDrawerEnvironment& env = Env(); // Env() const |
|
297 const MWsScreen* scr = env.Screen(iScreenId); // Screen(TInt) const |
|
298 const MWsScreenConfig* cfg = scr->ObjectInterface<MWsScreenConfig>(); // ObjectInterface() const |
|
299 } |
|
300 |
|
301 void CWsGcRedirector::SendInfo() |
|
302 { |
|
303 TPckgBuf<TRedirectorInfo> buf; |
|
304 MWsScreen* scr = Env().Screen(iScreenId); |
|
305 if (scr) |
|
306 { |
|
307 buf().iSignature = KRedirectorInfoSig; |
|
308 buf().iFrontBufferInterface = scr->ObjectInterface<MWsFrontBuffer>(); |
|
309 buf().iBackBufferInterface = scr->ObjectInterface<MWsBackBuffer>(); |
|
310 buf().iScreenConfigInterface = scr->ObjectInterface<MWsScreenConfig>(); |
|
311 buf().iScreenBitmapHandle = iFrontBit->Handle(); |
|
312 buf().iFlickerBitmapHandle = iBackBit? iBackBit->Handle() : 0; |
|
313 buf().iUpdateCounter = iUpdateCounter; |
|
314 } |
|
315 TInt err = SendMessage(buf); |
|
316 __ASSERT_ALWAYS(err>=KErrNone, User::Invariant()); |
|
317 } |
|
318 |
|
319 void CWsGcRedirector::DoHandleEvent(const TWservCrEvent& aEvent) |
|
320 { |
|
321 if (aEvent.ScreenNumber()==iScreenId) |
|
322 { |
|
323 switch(aEvent.Type()) |
|
324 { |
|
325 case TWservCrEvent::EScreenUpdated: |
|
326 ++iUpdateCounter; |
|
327 break; |
|
328 case TWservCrEvent::EDeviceOrientationChanged: |
|
329 case TWservCrEvent::EScreenOrientationChanged: |
|
330 { |
|
331 CFbsBitGc::TGraphicsOrientation orientation=aEvent.Orientation(); |
|
332 TSize bmpSize; |
|
333 if (orientation==CFbsBitGc::EGraphicsOrientationNormal || orientation==CFbsBitGc::EGraphicsOrientationRotated180) |
|
334 bmpSize=iDefaultSize; |
|
335 else |
|
336 bmpSize.SetSize(iDefaultSize.iHeight,iDefaultSize.iWidth); |
|
337 const TSize fBufSize(iFrontBit->SizeInPixels()); |
|
338 if (fBufSize!=bmpSize) |
|
339 { |
|
340 __ASSERT_DEBUG(fBufSize.iWidth==bmpSize.iHeight && fBufSize.iHeight==bmpSize.iWidth, User::Invariant()); |
|
341 iFrontDev->SwapWidthAndHeight(); |
|
342 iFrontGc->Activate(iFrontDev); |
|
343 } |
|
344 } |
|
345 break; |
|
346 } |
|
347 } |
|
348 } |
|
349 |
|
350 #ifdef __WINS__ |
|
351 TInt CWsGcRedirector::UpdateDebugWindowsCallback(TAny* aSelf) |
|
352 { |
|
353 CWsGcRedirector* self = static_cast<CWsGcRedirector*>(aSelf); |
|
354 if(!self) |
|
355 return KErrArgument; |
|
356 |
|
357 if(self->iFrontWin && self->iFrontBit) |
|
358 { |
|
359 CFbsBitmap* bitmap = self->iFrontBit; |
|
360 bitmap->LockHeap(); |
|
361 self->iFrontWin->Refresh(bitmap->SizeInPixels(), bitmap->DisplayMode(), bitmap->DataAddress()); |
|
362 bitmap->UnlockHeap(); |
|
363 } |
|
364 |
|
365 if(self->iBackWin && self->iBackBit) |
|
366 { |
|
367 CFbsBitmap* bitmap = self->iBackBit; |
|
368 bitmap->LockHeap(); |
|
369 self->iBackWin->Refresh(bitmap->SizeInPixels(), bitmap->DisplayMode(), bitmap->DataAddress()); |
|
370 bitmap->UnlockHeap(); |
|
371 } |
|
372 return KErrNone; |
|
373 } |
|
374 #endif |