|
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 /** |
|
17 @file |
|
18 @test |
|
19 @internalComponent - Internal Symbian test code |
|
20 */ |
|
21 |
|
22 |
|
23 #include "egltest_surface.h" |
|
24 #include "egltest_endpoint_images.h" |
|
25 #include <graphics/surfaceconfiguration.h> |
|
26 #include <e32std.h> |
|
27 #include <e32math.h> |
|
28 #include <VG/vgu.h> |
|
29 |
|
30 |
|
31 #define SURF_ASSERT(x) { if (!(x)) { RDebug::Printf("ASSERT(%s) failed at %s:%d", #x, __FILE__, __LINE__); User::Panic(_L("ASSERT SURF"), __LINE__); }} |
|
32 |
|
33 // Macros for indicating what is what. |
|
34 #define SIZE(x, y) x, y |
|
35 #define Buffers(x) x |
|
36 #define DefaultAlignment 32 // Pick some value that is valid. |
|
37 #define Alignment(x) x |
|
38 #define Stride(x) x |
|
39 #define DefaultStride 0 |
|
40 // Note: Offset to first buffer. |
|
41 #define Offset(x) x |
|
42 #define WindowPos(x, y) x, y |
|
43 #define WindowMode(m) m |
|
44 |
|
45 #define LARGEST_POSSIBLE_FLAG 0x80000000 |
|
46 |
|
47 static const TSurfaceParamsCommon KSurfaceParams[] = |
|
48 { |
|
49 { |
|
50 EStandardSurface, |
|
51 SIZE(100, 100), |
|
52 Buffers(2), |
|
53 DefaultAlignment, |
|
54 DefaultStride, |
|
55 Offset(0), |
|
56 EUidPixelFormatARGB_8888_PRE, |
|
57 EFalse, |
|
58 { 0 }, |
|
59 WindowPos(0, 0), |
|
60 WindowMode(EColor16MAP) |
|
61 }, |
|
62 { |
|
63 EBadAttribSurface, |
|
64 SIZE(100, 100), |
|
65 Buffers(2), |
|
66 DefaultAlignment, |
|
67 DefaultStride, |
|
68 Offset(0), |
|
69 EUidPixelFormatARGB_8888_PRE, |
|
70 ETrue, |
|
71 { 1, 1, EGL_NONE }, |
|
72 WindowPos(0, 0), |
|
73 WindowMode(EColor16MAP) |
|
74 }, |
|
75 { |
|
76 EEmptyAttribSurface, |
|
77 SIZE(100, 100), |
|
78 Buffers(2), |
|
79 DefaultAlignment, |
|
80 DefaultStride, |
|
81 Offset(0), |
|
82 EUidPixelFormatARGB_8888_PRE, |
|
83 ETrue, |
|
84 { EGL_NONE }, |
|
85 WindowPos(0, 0), |
|
86 WindowMode(EColor16MAP) |
|
87 }, |
|
88 { |
|
89 EStandard128sqSurface, |
|
90 SIZE(128, 128), |
|
91 Buffers(3), |
|
92 DefaultAlignment, |
|
93 DefaultStride, |
|
94 Offset(0), |
|
95 EUidPixelFormatARGB_8888_PRE, |
|
96 EFalse, |
|
97 { 0 }, |
|
98 WindowPos(20, 20), |
|
99 WindowMode(EColor16MAP) |
|
100 }, |
|
101 { |
|
102 EUnusualStrideSurface, |
|
103 SIZE(167,263), |
|
104 Buffers(2), |
|
105 Alignment(8), |
|
106 Stride(167*4+64), |
|
107 Offset(200), |
|
108 EUidPixelFormatARGB_8888_PRE, |
|
109 EFalse, |
|
110 { 0 }, |
|
111 WindowPos(0, 0), |
|
112 WindowMode(EColor16MAP) |
|
113 }, |
|
114 { |
|
115 EUnalignedPixelSizeSurface, |
|
116 SIZE(103, 107), |
|
117 Buffers(2), |
|
118 Alignment(8), |
|
119 Stride(103*4), |
|
120 Offset(0), |
|
121 EUidPixelFormatARGB_8888_PRE, |
|
122 EFalse, |
|
123 { 0 }, |
|
124 WindowPos(0, 0), |
|
125 WindowMode(EColor16MAP) |
|
126 }, |
|
127 { |
|
128 ELargeSurface, |
|
129 SIZE(800, 600), |
|
130 Buffers(2), |
|
131 DefaultAlignment, |
|
132 DefaultStride, |
|
133 Offset(0), |
|
134 EUidPixelFormatARGB_8888_PRE, |
|
135 EFalse, |
|
136 { 0 }, |
|
137 WindowPos(0, 0), |
|
138 WindowMode(EColor16MAP) |
|
139 }, |
|
140 { |
|
141 ELargestPossibleSurface, |
|
142 SIZE(LARGEST_POSSIBLE_FLAG, LARGEST_POSSIBLE_FLAG), |
|
143 Buffers(2), |
|
144 DefaultAlignment, |
|
145 DefaultStride, |
|
146 Offset(0), |
|
147 EUidPixelFormatARGB_8888_PRE, |
|
148 EFalse, |
|
149 { 0 }, |
|
150 WindowPos(0, 0), |
|
151 WindowMode(EColor16MAP) |
|
152 }, |
|
153 { |
|
154 ESmallSurface, |
|
155 SIZE(16, 16), |
|
156 Buffers(1), |
|
157 DefaultAlignment, |
|
158 DefaultStride, |
|
159 Offset(0), |
|
160 EUidPixelFormatARGB_8888_PRE, |
|
161 EFalse, |
|
162 { 0 }, |
|
163 WindowPos(0, 0), |
|
164 WindowMode(EColor16MAP) |
|
165 }, |
|
166 { |
|
167 ETinySurface, |
|
168 SIZE(8, 8), |
|
169 Buffers(1), |
|
170 DefaultAlignment, |
|
171 DefaultStride, |
|
172 Offset(0), |
|
173 EUidPixelFormatARGB_8888_PRE, |
|
174 EFalse, |
|
175 { 0 }, |
|
176 WindowPos(0, 0), |
|
177 WindowMode(EColor16MAP) |
|
178 }, |
|
179 }; |
|
180 |
|
181 const TInt KSurfaceMaxIndex = sizeof(KSurfaceParams) / sizeof(KSurfaceParams[0]); |
|
182 |
|
183 struct TSurfaceSize |
|
184 { |
|
185 TInt iWidth; |
|
186 TInt iHeight; |
|
187 }; |
|
188 |
|
189 static const TSurfaceSize KSurfaceSizes[] = |
|
190 { |
|
191 { 320, 240 }, |
|
192 { 640, 480 }, |
|
193 { 720, 480 }, |
|
194 { 854, 480 }, |
|
195 { 720, 576 }, |
|
196 { 854, 576 }, |
|
197 { 1280, 720 }, |
|
198 { 1024, 768 }, |
|
199 { 1280, 1024 }, |
|
200 { 1920, 1080 }, |
|
201 { 1600, 1200 }, |
|
202 #if 0 |
|
203 { 2048, 1536 }, |
|
204 { 2560, 1920 }, |
|
205 { 3648, 2736 }, |
|
206 { 4216, 2638 }, |
|
207 { 4000, 3000 }, |
|
208 { 4616, 2600 }, |
|
209 #endif |
|
210 }; |
|
211 |
|
212 const TInt KMaxSurfaceSizes = sizeof(KSurfaceSizes) / sizeof(KSurfaceSizes[0]); |
|
213 |
|
214 LOCAL_C TUint RandomNumberInRange(TUint aLow, TUint aHigh) |
|
215 { |
|
216 TReal32 rand = Math::Random(); |
|
217 rand /= KMaxTUint; |
|
218 rand *= aHigh - aLow; |
|
219 rand += aLow; |
|
220 return TUint(rand); |
|
221 } |
|
222 |
|
223 |
|
224 void CSurface::CreateL(TInt aIndex) |
|
225 { |
|
226 CreateL(aIndex, TPoint(0, 0)); |
|
227 } |
|
228 |
|
229 |
|
230 TSize CSurface::Size() |
|
231 { |
|
232 return iActualSize; |
|
233 } |
|
234 |
|
235 |
|
236 TInt CSurface::SizeInBytes() const |
|
237 { |
|
238 RSurfaceManager::TInfoBuf infoBuf; |
|
239 RSurfaceManager surfMgr; |
|
240 TInt err = surfMgr.Open(); |
|
241 if (err != KErrNone) |
|
242 { |
|
243 RDebug::Printf("Error opening surface manager... Err=%d", err); |
|
244 return 0; |
|
245 } |
|
246 err = surfMgr.SurfaceInfo(SurfaceId(), infoBuf); |
|
247 if (err != KErrNone) |
|
248 { |
|
249 RDebug::Printf("Could not get surface info - err = %d", err); |
|
250 return 0; |
|
251 } |
|
252 TInt size = infoBuf().iBuffers * infoBuf().iSize.iHeight * infoBuf().iStride; |
|
253 surfMgr.Close(); |
|
254 return size; |
|
255 } |
|
256 |
|
257 |
|
258 CRawSurface* CRawSurface::NewL() |
|
259 { |
|
260 CRawSurface* obj = new (ELeave) CRawSurface(); |
|
261 CleanupStack::PushL(obj); |
|
262 obj->ConstructL(); |
|
263 CleanupStack::Pop(obj); |
|
264 return obj; |
|
265 } |
|
266 |
|
267 |
|
268 |
|
269 CRawSurface::CRawSurface() : iDrawBuffer(0), iBuffers(0) |
|
270 { |
|
271 } |
|
272 |
|
273 |
|
274 void CRawSurface::ConstructL() |
|
275 { |
|
276 iSurfaceId = TSurfaceId::CreateNullId(); |
|
277 User::LeaveIfError(iSurfaceManager.Open()); |
|
278 User::LeaveIfError(iSurfaceUpdate.Connect()); |
|
279 } |
|
280 |
|
281 |
|
282 CRawSurface::~CRawSurface() |
|
283 { |
|
284 iSurfaceUpdate.Close(); |
|
285 if(!iSurfaceId.IsNull()) |
|
286 { |
|
287 iSurfaceManager.CloseSurface(iSurfaceId); |
|
288 } |
|
289 iSurfaceManager.Close(); |
|
290 } |
|
291 |
|
292 |
|
293 TInt CRawSurface::PixelSize(TUidPixelFormat aPixelFormat) |
|
294 { |
|
295 switch(aPixelFormat) |
|
296 { |
|
297 case EUidPixelFormatARGB_8888_PRE: |
|
298 case EUidPixelFormatARGB_8888: |
|
299 case EUidPixelFormatABGR_8888: |
|
300 case EUidPixelFormatABGR_8888_PRE: |
|
301 return 4; |
|
302 |
|
303 case EUidPixelFormatARGB_4444: |
|
304 case EUidPixelFormatRGB_565: |
|
305 return 2; |
|
306 |
|
307 default: |
|
308 SURF_ASSERT(0); |
|
309 break; |
|
310 } |
|
311 return 0; // Make sure no compiler moans about "not all paths return a value". |
|
312 } |
|
313 |
|
314 |
|
315 void CRawSurface::GetSurfAttribs(RSurfaceManager::TSurfaceCreationAttributesBuf &aSurfaceAttribs, |
|
316 TInt aIndex, TInt aSizeIndex) |
|
317 { |
|
318 SURF_ASSERT(aIndex < KSurfaceMaxIndex); |
|
319 SURF_ASSERT(aIndex == KSurfaceParams[aIndex].iIndex); |
|
320 iParamIndex = aIndex; |
|
321 if (KSurfaceParams[aIndex].iXSize & LARGEST_POSSIBLE_FLAG) |
|
322 { |
|
323 |
|
324 aSurfaceAttribs().iSize = |
|
325 TSize(KSurfaceSizes[aSizeIndex].iWidth, KSurfaceSizes[aSizeIndex].iHeight); |
|
326 } |
|
327 else |
|
328 { |
|
329 aSurfaceAttribs().iSize = |
|
330 TSize(KSurfaceParams[aIndex].iXSize, KSurfaceParams[aIndex].iYSize); |
|
331 } |
|
332 iBuffers = KSurfaceParams[aIndex].iBuffers; |
|
333 aSurfaceAttribs().iBuffers = iBuffers; |
|
334 aSurfaceAttribs().iPixelFormat = KSurfaceParams[aIndex].iPixelFormat; |
|
335 TInt stride = KSurfaceParams[aIndex].iStrideInBytes; |
|
336 if (stride == 0) |
|
337 { |
|
338 stride = aSurfaceAttribs().iSize.iWidth * PixelSize(KSurfaceParams[aIndex].iPixelFormat); |
|
339 } |
|
340 aSurfaceAttribs().iStride = stride; |
|
341 aSurfaceAttribs().iOffsetToFirstBuffer = KSurfaceParams[aIndex].iOffsetToFirstBuffer; |
|
342 aSurfaceAttribs().iAlignment = KSurfaceParams[aIndex].iAlignment; |
|
343 aSurfaceAttribs().iContiguous = EFalse; |
|
344 aSurfaceAttribs().iCacheAttrib = RSurfaceManager::ECached; |
|
345 aSurfaceAttribs().iOffsetBetweenBuffers = 0; |
|
346 aSurfaceAttribs().iSurfaceHints = NULL; |
|
347 aSurfaceAttribs().iHintCount = 0; |
|
348 aSurfaceAttribs().iMappable = ETrue; |
|
349 } |
|
350 |
|
351 |
|
352 void CRawSurface::CreateL(TInt aIndex, const TPoint &/* aPoint */) |
|
353 { |
|
354 RSurfaceManager::TSurfaceCreationAttributesBuf surfaceAttribs; |
|
355 SURF_ASSERT(aIndex < KSurfaceMaxIndex); |
|
356 TInt sizeIndex = 0; |
|
357 if (KSurfaceParams[aIndex].iXSize & LARGEST_POSSIBLE_FLAG) |
|
358 { |
|
359 sizeIndex = KMaxSurfaceSizes-1; |
|
360 |
|
361 } |
|
362 TInt err = KErrNone; |
|
363 do |
|
364 { |
|
365 GetSurfAttribs(surfaceAttribs, aIndex, sizeIndex); |
|
366 err = iSurfaceManager.CreateSurface(surfaceAttribs, iSurfaceId); |
|
367 iActualSize = surfaceAttribs().iSize; |
|
368 sizeIndex--; |
|
369 } |
|
370 while(err != KErrNone && sizeIndex >= 0); |
|
371 User::LeaveIfError(err); |
|
372 } |
|
373 |
|
374 |
|
375 TUint8* CRawSurface::MapSurfaceAndGetInfoLC(RSurfaceManager::TSurfaceInfoV01& aInfo) |
|
376 { |
|
377 SURF_ASSERT(!iSurfaceId.IsNull()); |
|
378 User::LeaveIfError(iSurfaceManager.MapSurface(iSurfaceId, iSurfaceChunk)); |
|
379 CleanupClosePushL(iSurfaceChunk); |
|
380 RSurfaceManager::TInfoBuf infoBuf; |
|
381 User::LeaveIfError(iSurfaceManager.SurfaceInfo(iSurfaceId, infoBuf)); |
|
382 aInfo = infoBuf(); |
|
383 TInt offset = -1000; // So we hopefully detect when it goes horribly wrong. |
|
384 User::LeaveIfError(iSurfaceManager.GetBufferOffset(iSurfaceId, iDrawBuffer, offset)); |
|
385 SURF_ASSERT(offset >= 0); |
|
386 return iSurfaceChunk.Base() + offset; |
|
387 } |
|
388 |
|
389 |
|
390 void CRawSurface::DrawContentL(TInt aImageIndex) |
|
391 { |
|
392 CTestCFbsImage *image = CTestCFbsImage::NewL(aImageIndex); |
|
393 CleanupStack::PushL(image); |
|
394 |
|
395 RSurfaceManager::TSurfaceInfoV01 info; |
|
396 TUint8 *dataAddress = MapSurfaceAndGetInfoLC(info); |
|
397 TInt stride = info.iStride; |
|
398 |
|
399 CFbsBitmap *bitmap = image->Bitmap(); |
|
400 TDisplayMode displaymode = bitmap->DisplayMode(); |
|
401 TInt pixelStride = stride / CFbsBitmap::ScanLineLength(1, displaymode); |
|
402 for(TInt y = 0; y < image->Size().iHeight; y++) |
|
403 { |
|
404 TPtr8 buf(dataAddress + y * stride, stride); |
|
405 |
|
406 // TODO: We need to check that the bitsperpixel matches between the surface and bitmap. |
|
407 bitmap->GetScanLine(buf, TPoint(0, y), pixelStride, displaymode); |
|
408 } |
|
409 |
|
410 CleanupStack::PopAndDestroy(2, image); |
|
411 } |
|
412 |
|
413 void CRawSurface::DrawContentL(const TRgb& aColour) |
|
414 { |
|
415 //Map the surface and get its info. |
|
416 RSurfaceManager::TSurfaceInfoV01 surfaceInfo; |
|
417 TUint32* buffer = (TUint32*)MapSurfaceAndGetInfoLC(surfaceInfo); |
|
418 |
|
419 //Currently this function only supports drawing into ARGB_8888_PRE surfaces. |
|
420 //This is because the only test that uses this function uses this type of surface. |
|
421 //If this functionallity needs expanding, you must correctly convert the TRgb colour |
|
422 //and pack it into the surface buffer correctly. |
|
423 SURF_ASSERT(surfaceInfo.iPixelFormat == EUidPixelFormatARGB_8888_PRE); |
|
424 |
|
425 TUint32 fillColour = aColour._Color16MAP(); |
|
426 |
|
427 //Loop over each pixel in the surface and colour it. |
|
428 //This is deliberately slow since it is only used for the tearing test |
|
429 //and we want to spend most of our time drawing so that the chances of the other thread |
|
430 //picking up a buffer in the middle of drawing is increased. |
|
431 for(TInt y=0; y < surfaceInfo.iSize.iHeight; ++y) |
|
432 { |
|
433 for(TInt x=0; x < surfaceInfo.iSize.iWidth; ++x) |
|
434 { |
|
435 buffer[x] = fillColour; |
|
436 } |
|
437 buffer += surfaceInfo.iStride >> 2; |
|
438 } |
|
439 |
|
440 CleanupStack::PopAndDestroy(); |
|
441 } |
|
442 |
|
443 |
|
444 void CRawSurface::DrawComplexL(const TRgb& aColour) |
|
445 { |
|
446 DrawContentL(aColour); |
|
447 } |
|
448 |
|
449 |
|
450 TInt CRawSurface::SubmitContent(TBool aShouldWaitForDisplay, TInt /* aRectsIndex */) |
|
451 { |
|
452 TRequestStatus displayNotify = KRequestPending; |
|
453 TTimeStamp timeStamp; |
|
454 |
|
455 if(aShouldWaitForDisplay) |
|
456 { |
|
457 Notify(ENotifyWhenDisplayed, displayNotify, 0); |
|
458 } |
|
459 |
|
460 TInt err = iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurfaceId, iDrawBuffer, NULL); |
|
461 if (err != KErrNone) |
|
462 { |
|
463 if (err != KErrNone) |
|
464 { |
|
465 RDebug::Printf("%s:%d: SubmitUpdate gave unexpected error %d", __FILE__, __LINE__, err); |
|
466 } |
|
467 return err; |
|
468 } |
|
469 iDrawBuffer = (iDrawBuffer + 1) % iBuffers; |
|
470 |
|
471 if(aShouldWaitForDisplay) |
|
472 { |
|
473 TUint32 dummy; |
|
474 err = WaitFor(ENotifyWhenDisplayed, displayNotify, 100 * 1000, dummy); |
|
475 if (err != KErrNone && err != KErrNotVisible && err != KErrOverflow) |
|
476 { |
|
477 // RDebug::Printf("%s:%d: NotifyWhenDisplayed gave unexpected error %d", __FILE__, __LINE__, err); |
|
478 return err; |
|
479 } |
|
480 } |
|
481 return KErrNone; |
|
482 } |
|
483 |
|
484 |
|
485 TSurfaceId CRawSurface::SurfaceId() const |
|
486 { |
|
487 return iSurfaceId; |
|
488 } |
|
489 |
|
490 |
|
491 void CRawSurface::GetSurfaceParamsL(TSurfaceParamsRemote &aParams) |
|
492 { |
|
493 aParams.iCommonParams = KSurfaceParams[iParamIndex]; |
|
494 aParams.iCommonParams.iBuffers = iBuffers; // May have been changed if it's a single buffered surface... |
|
495 aParams.iSurfaceId = SurfaceId(); |
|
496 } |
|
497 |
|
498 const TText *CRawSurface::GetSurfaceTypeStr() const |
|
499 { |
|
500 return _S("CRawSurface"); |
|
501 } |
|
502 |
|
503 TInt CRawSurface::Notify(TNotification aWhen, TRequestStatus& aStatus, TUint32 aXTimes) |
|
504 { |
|
505 aStatus = KRequestPending; |
|
506 switch(aWhen) |
|
507 { |
|
508 case ENotifyWhenAvailable: |
|
509 iSurfaceUpdate.NotifyWhenAvailable(aStatus); |
|
510 break; |
|
511 case ENotifyWhenDisplayed: |
|
512 iSurfaceUpdate.NotifyWhenDisplayed(aStatus, iTimeStamp); |
|
513 break; |
|
514 case ENotifyWhenDispXTimes: |
|
515 iSurfaceUpdate.NotifyWhenDisplayedXTimes(aXTimes, aStatus); |
|
516 break; |
|
517 default: |
|
518 RDebug::Printf("%s:%d: Invalid notification: %d. Panicking...", __FILE__, __LINE__, aWhen); |
|
519 User::Panic(_L("CRawSurface::Notify()"), __LINE__); |
|
520 break; |
|
521 } |
|
522 return KErrNone; |
|
523 } |
|
524 |
|
525 |
|
526 TInt CRawSurface::WaitFor(TNotification aWhen, TRequestStatus& aStatus, TInt aTimeoutInMicroSeconds, TUint32& aTimeStamp) |
|
527 { |
|
528 RTimer timer; |
|
529 TInt err = timer.CreateLocal(); |
|
530 if (err != KErrNone) |
|
531 { |
|
532 RDebug::Printf("%s:%d: Could not create timer... err= %d", __FILE__, __LINE__, err); |
|
533 return err; |
|
534 } |
|
535 TRequestStatus timerStatus = KRequestPending; |
|
536 #if __WINS__ |
|
537 // Windows timer isn't very precise - add some "fuzz" to the timeout to ensure we do not wait "too little". |
|
538 const TInt KTimeOutExtra = 20000; |
|
539 #else |
|
540 // On hardware, we should be able to run with less "fuzz". |
|
541 const TInt KTimeOutExtra = 10000; |
|
542 #endif |
|
543 timer.HighRes(timerStatus, aTimeoutInMicroSeconds + KTimeOutExtra); |
|
544 User::WaitForRequest(timerStatus, aStatus); |
|
545 if (aStatus == KRequestPending) |
|
546 { |
|
547 if (aWhen == ENotifyWhenDisplayed) |
|
548 { |
|
549 aTimeStamp = User::FastCounter(); |
|
550 } |
|
551 return KErrTimedOut; |
|
552 } |
|
553 if (aWhen == ENotifyWhenDisplayed) |
|
554 { |
|
555 aTimeStamp = iTimeStamp(); |
|
556 } |
|
557 timer.Cancel(); |
|
558 timer.Close(); |
|
559 TInt result = aStatus.Int(); |
|
560 aStatus = KRequestPending; |
|
561 return result; |
|
562 } |
|
563 |
|
564 const TText *CRawSingleBufferSurface::GetSurfaceTypeStr() const |
|
565 { |
|
566 return _S("CRawSingleBufferedSurface"); |
|
567 } |
|
568 |
|
569 CRawSingleBufferSurface *CRawSingleBufferSurface::NewL() |
|
570 { |
|
571 CRawSingleBufferSurface* obj = new (ELeave) CRawSingleBufferSurface(); |
|
572 CleanupStack::PushL(obj); |
|
573 obj->ConstructL(); |
|
574 CleanupStack::Pop(obj); |
|
575 return obj; |
|
576 } |
|
577 |
|
578 |
|
579 void CRawSingleBufferSurface::CreateL(TInt aIndex, const TPoint & /*aPoint */) |
|
580 { |
|
581 RSurfaceManager::TSurfaceCreationAttributesBuf surfaceAttribs; |
|
582 |
|
583 TInt sizeIndex = 0; |
|
584 if (KSurfaceParams[aIndex].iXSize & LARGEST_POSSIBLE_FLAG) |
|
585 { |
|
586 sizeIndex = KMaxSurfaceSizes-1; |
|
587 } |
|
588 TInt err = KErrNone; |
|
589 do |
|
590 { |
|
591 GetSurfAttribs(surfaceAttribs, aIndex, sizeIndex); |
|
592 iBuffers = 1; |
|
593 surfaceAttribs().iBuffers = 1; |
|
594 err = iSurfaceManager.CreateSurface(surfaceAttribs, iSurfaceId); |
|
595 iActualSize = surfaceAttribs().iSize; |
|
596 sizeIndex--; |
|
597 } |
|
598 while(err != KErrNone && sizeIndex >= 0); |
|
599 } |
|
600 |
|
601 CRawSingleBufferSurface::~CRawSingleBufferSurface() |
|
602 { |
|
603 } |
|
604 |
|
605 |
|
606 TInt CEglSurfaceBase::Activate() |
|
607 { |
|
608 if (!eglMakeCurrent(iDisplay, iSurface, iSurface, iContext)) |
|
609 { |
|
610 EGLint err = eglGetError(); |
|
611 RDebug::Printf("%s:%d: eglMakeCurrent gave error 0x%x", __FILE__, __LINE__, err); |
|
612 return KErrBadHandle; |
|
613 } |
|
614 return KErrNone; |
|
615 } |
|
616 |
|
617 void CEglSurfaceBase::ActivateL() |
|
618 { |
|
619 User::LeaveIfError(Activate()); |
|
620 } |
|
621 |
|
622 void CEglSurfaceBase::DrawComplexL(const TRgb& aColour) |
|
623 { |
|
624 ActivateL(); |
|
625 |
|
626 TSize size; |
|
627 eglQuerySurface(iDisplay, iSurface, EGL_WIDTH, &size.iWidth); |
|
628 eglQuerySurface(iDisplay, iSurface, EGL_HEIGHT, &size.iHeight); |
|
629 |
|
630 //Paint lots of random circles to keep the GPU busy. |
|
631 for(TInt i=0; i < 300; i++) |
|
632 { |
|
633 VGPaint paint = vgCreatePaint(); |
|
634 VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_APPEND_TO); |
|
635 |
|
636 TInt minDim = Min(size.iWidth, size.iHeight); |
|
637 VGfloat cx = RandomNumberInRange(0, size.iWidth); |
|
638 VGfloat cy = RandomNumberInRange(0, size.iHeight); |
|
639 VGfloat diameter = RandomNumberInRange(minDim / 20, minDim / 3); |
|
640 TRgb fillColour(RandomNumberInRange(0, 255), RandomNumberInRange(0, 255), RandomNumberInRange(0, 255), RandomNumberInRange(0, 255)); |
|
641 |
|
642 vguEllipse(path, cx, cy, diameter, diameter); |
|
643 vgSetPaint(paint, VG_FILL_PATH); |
|
644 vgSetColor(paint, fillColour.Value()); |
|
645 vgDrawPath(path, VG_FILL_PATH); |
|
646 |
|
647 vgDestroyPath(path); |
|
648 vgDestroyPaint(paint); |
|
649 } |
|
650 |
|
651 //Paint the top corner with aColour so we can identify the drawing. |
|
652 VGfloat fillColour[4]; |
|
653 fillColour[0] = (VGfloat)aColour.Red() / 255.0f; |
|
654 fillColour[1] = (VGfloat)aColour.Green() / 255.0f; |
|
655 fillColour[2] = (VGfloat)aColour.Blue() / 255.0f; |
|
656 fillColour[3] = (VGfloat)aColour.Alpha() / 255.0f; |
|
657 |
|
658 vgSetfv(VG_CLEAR_COLOR, 4, fillColour); |
|
659 vgClear(0, 0, 20, size.iHeight); |
|
660 } |
|
661 |
|
662 void CEglSurfaceBase::DrawContentL(const TRgb& aColour) |
|
663 { |
|
664 ActivateL(); |
|
665 |
|
666 TSize size; |
|
667 eglQuerySurface(iDisplay, iSurface, EGL_WIDTH, &size.iWidth); |
|
668 eglQuerySurface(iDisplay, iSurface, EGL_HEIGHT, &size.iHeight); |
|
669 |
|
670 VGfloat fillColour[4]; |
|
671 fillColour[0] = (VGfloat)aColour.Red() / 255.0f; |
|
672 fillColour[1] = (VGfloat)aColour.Green() / 255.0f; |
|
673 fillColour[2] = (VGfloat)aColour.Blue() / 255.0f; |
|
674 fillColour[3] = (VGfloat)aColour.Alpha() / 255.0f; |
|
675 |
|
676 vgSetfv(VG_CLEAR_COLOR, 4, fillColour); |
|
677 vgClear(0, 0, size.iWidth, size.iHeight); |
|
678 } |
|
679 |
|
680 void CEglSurfaceBase::CreateL(TInt aIndex, const TPoint &aOffset) |
|
681 { |
|
682 SURF_ASSERT(aIndex < KSurfaceMaxIndex); |
|
683 SURF_ASSERT(aIndex == KSurfaceParams[aIndex].iIndex); |
|
684 |
|
685 TInt sizeIndex = 0; |
|
686 if (KSurfaceParams[aIndex].iXSize & LARGEST_POSSIBLE_FLAG) |
|
687 { |
|
688 sizeIndex = KMaxSurfaceSizes-1; |
|
689 } |
|
690 TInt err = KErrNone; |
|
691 do |
|
692 { |
|
693 TRAP(err, DoCreateL(aIndex, aOffset, sizeIndex)); |
|
694 sizeIndex--; |
|
695 } |
|
696 while(err != KErrNone && sizeIndex >= 0); |
|
697 if (err != KErrNone) |
|
698 { |
|
699 // RDebug::Printf("%s:%d: err=%d (%d x %d)", __FILE__, __LINE__, err, iActualSize.iWidth, iActualSize.iHeight); |
|
700 User::Leave(err); |
|
701 } |
|
702 } |
|
703 |
|
704 TInt CEglSurfaceBase::SubmitContent(TBool aShouldWaitForDisplay, TInt /* aRectsIndex */) |
|
705 { |
|
706 TInt err = Activate(); |
|
707 if (err != KErrNone) |
|
708 { |
|
709 return err; |
|
710 } |
|
711 if (!eglSwapBuffers(iDisplay, iSurface)) |
|
712 { |
|
713 EGLint err = eglGetError(); |
|
714 RDebug::Printf("%s:%d: eglSwapBuffers gave error 0x%x", __FILE__, __LINE__, err); |
|
715 return KErrBadHandle; |
|
716 } |
|
717 if (aShouldWaitForDisplay) |
|
718 { |
|
719 // We are cheating: We just wait for a bit to ensure that the swapbuffer is actually finished. |
|
720 // There is no way to determine how long this takes, so we just grab a number that should be |
|
721 // large enough... |
|
722 User::After(100 * 1000); // Wait 100ms. |
|
723 } |
|
724 return KErrNone; |
|
725 } |
|
726 |
|
727 void CEglSurfaceBase::DrawContentL(TInt aIndex) |
|
728 { |
|
729 ActivateL(); |
|
730 CTestVgImage *vgImage = CTestVgImage::NewL(aIndex); |
|
731 CleanupStack::PushL(vgImage); |
|
732 vgDrawImage(vgImage->VGImage()); |
|
733 CleanupStack::PopAndDestroy(vgImage); |
|
734 } |
|
735 |
|
736 void CEglSurfaceBase::GetSurfaceParamsL(TSurfaceParamsRemote &aParams) |
|
737 { |
|
738 RSurfaceManager surfaceManager; |
|
739 User::LeaveIfError(surfaceManager.Open()); |
|
740 RSurfaceManager::TInfoBuf infoBuf; |
|
741 TInt err = surfaceManager.SurfaceInfo(SurfaceId(), infoBuf); |
|
742 User::LeaveIfError(err); |
|
743 surfaceManager.Close(); |
|
744 RSurfaceManager::TSurfaceInfoV01& info = infoBuf(); |
|
745 aParams.iSurfaceId = SurfaceId(); |
|
746 aParams.iCommonParams.iAlignment = -1; // N/A |
|
747 aParams.iCommonParams.iBuffers = info.iBuffers; |
|
748 aParams.iCommonParams.iOffsetToFirstBuffer = -1; |
|
749 aParams.iCommonParams.iPixelFormat = info.iPixelFormat; |
|
750 aParams.iCommonParams.iStrideInBytes = info.iStride; |
|
751 aParams.iCommonParams.iXSize = info.iSize.iWidth; |
|
752 aParams.iCommonParams.iYSize = info.iSize.iHeight; |
|
753 aParams.iCommonParams.iUseAttribList = KSurfaceParams[iParamIndex].iUseAttribList; |
|
754 for(TInt i = 0; i < KNumAttribs; i++) |
|
755 { |
|
756 aParams.iCommonParams.iAttribs[i] = KSurfaceParams[iParamIndex].iAttribs[i]; |
|
757 } |
|
758 } |
|
759 |
|
760 |
|
761 TInt CEglSurfaceBase::Notify(TNotification /*aWhen*/, TRequestStatus& /*aStatus*/, TUint32 /*aXTImes*/) |
|
762 { |
|
763 return KErrNotSupported; |
|
764 } |
|
765 |
|
766 TInt CEglSurfaceBase::WaitFor(TNotification /*aWhen*/, TRequestStatus& /*aStatus*/, |
|
767 TInt /*aTimeoutinMicroseconds*/, TUint32 & /*aTimeStamp*/) |
|
768 { |
|
769 return KErrNotSupported; |
|
770 } |
|
771 |
|
772 void CEglSurfaceBase::BaseCreateL(TInt aIndex, EGLint aSurfaceType) |
|
773 { |
|
774 iParamIndex = aIndex; |
|
775 iDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); |
|
776 |
|
777 EGLint err; |
|
778 if (iDisplay == EGL_NO_DISPLAY) |
|
779 { |
|
780 err = eglGetError(); |
|
781 RDebug::Printf("%s:%d: err = 0x%x", __FILE__, __LINE__, err); |
|
782 User::Leave(KErrNotSupported); |
|
783 } |
|
784 |
|
785 EGLint nConfigs = 0; |
|
786 |
|
787 // TODO: Need to use differnet config attribs based on aIndex. |
|
788 EGLint configAttribs[] = |
|
789 { |
|
790 EGL_BUFFER_SIZE, 32, |
|
791 EGL_RED_SIZE, 8, |
|
792 EGL_GREEN_SIZE, 8, |
|
793 EGL_BLUE_SIZE, 8, |
|
794 EGL_ALPHA_SIZE, 8, |
|
795 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, |
|
796 EGL_RENDERABLE_TYPE,EGL_OPENVG_BIT, |
|
797 EGL_NONE |
|
798 }; |
|
799 |
|
800 // Update surfacetype type to match |
|
801 for(TInt i = 0; configAttribs[i] != EGL_NONE; i += 2) |
|
802 { |
|
803 if (configAttribs[i] == EGL_SURFACE_TYPE) |
|
804 { |
|
805 configAttribs[i+1] = aSurfaceType; |
|
806 } |
|
807 } |
|
808 // Need some way to configure the attribs ... |
|
809 eglChooseConfig(iDisplay, configAttribs, &iConfig, 1, &nConfigs); |
|
810 if (!nConfigs) |
|
811 { |
|
812 err = eglGetError(); |
|
813 RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err); |
|
814 User::Leave(KErrNotSupported); |
|
815 } |
|
816 |
|
817 if (!eglBindAPI(EGL_OPENVG_API)) |
|
818 { |
|
819 err = eglGetError(); |
|
820 RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err); |
|
821 User::Leave(KErrNotSupported); |
|
822 } |
|
823 iContext = eglCreateContext(iDisplay, iConfig, 0, NULL); |
|
824 if (iContext == EGL_NO_CONTEXT) |
|
825 { |
|
826 err = eglGetError(); |
|
827 //RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err); |
|
828 User::Leave(KErrNotSupported); |
|
829 } |
|
830 } |
|
831 |
|
832 void CEglSurfaceBase::Destroy() |
|
833 { |
|
834 eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
|
835 if (iSurface != EGL_NO_SURFACE) |
|
836 { |
|
837 eglDestroySurface(iDisplay, iSurface); |
|
838 iSurface = EGL_NO_SURFACE; |
|
839 } |
|
840 |
|
841 if (iDisplay != EGL_NO_DISPLAY) |
|
842 { |
|
843 eglDestroyContext(iDisplay, iContext); |
|
844 } |
|
845 } |
|
846 |
|
847 |
|
848 class CWindow: public CBase |
|
849 { |
|
850 public: |
|
851 static CWindow *NewL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex); |
|
852 RWindow& Window(); |
|
853 ~CWindow(); |
|
854 private: |
|
855 void ConstructL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex); |
|
856 CWindow(); |
|
857 |
|
858 private: |
|
859 RWindow iWindow; |
|
860 RWindowGroup iWindowGroup; |
|
861 RWsSession iWsSession; |
|
862 }; |
|
863 |
|
864 |
|
865 CWindow* CWindow::NewL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex) |
|
866 { |
|
867 CWindow *self = new (ELeave) CWindow; |
|
868 CleanupStack::PushL(self); |
|
869 self->ConstructL(aIndex, aOffset, aSizeIndex); |
|
870 CleanupStack::Pop(self); |
|
871 return self; |
|
872 } |
|
873 |
|
874 |
|
875 void CWindow::ConstructL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex) |
|
876 { |
|
877 RFbsSession::Connect(); |
|
878 if (aIndex >= KSurfaceMaxIndex) |
|
879 { |
|
880 User::Leave(KErrOverflow); |
|
881 } |
|
882 User::LeaveIfError(iWsSession.Connect()); |
|
883 iWindowGroup = RWindowGroup(iWsSession); |
|
884 User::LeaveIfError(iWindowGroup.Construct((TUint32)this)); |
|
885 iWindow = RWindow(iWsSession); |
|
886 User::LeaveIfError(iWindow.Construct(iWindowGroup, -1U)); |
|
887 TSurfaceParamsCommon winAttrib = KSurfaceParams[aIndex]; |
|
888 TSize winSize; |
|
889 if (winAttrib.iXSize & LARGEST_POSSIBLE_FLAG) |
|
890 { |
|
891 winSize = TSize(KSurfaceSizes[aSizeIndex].iWidth, KSurfaceSizes[aSizeIndex].iHeight); |
|
892 } |
|
893 else |
|
894 { |
|
895 winSize = TSize(winAttrib.iXSize, winAttrib.iYSize); |
|
896 } |
|
897 iWindow.SetExtent(TPoint(winAttrib.iXPos + aOffset.iX, winAttrib.iYPos + aOffset.iY), winSize); |
|
898 iWindow.SetRequiredDisplayMode(winAttrib.iDisplayMode); |
|
899 iWindow.Activate(); |
|
900 } |
|
901 |
|
902 |
|
903 CWindow::~CWindow() |
|
904 { |
|
905 iWindow.Close(); |
|
906 iWindowGroup.Close(); |
|
907 iWsSession.Close(); |
|
908 RFbsSession::Disconnect(); |
|
909 } |
|
910 |
|
911 |
|
912 CWindow::CWindow() |
|
913 { |
|
914 } |
|
915 |
|
916 |
|
917 RWindow& CWindow::Window() |
|
918 { |
|
919 return iWindow; |
|
920 } |
|
921 |
|
922 |
|
923 CEglWindowSurface* CEglWindowSurface::NewL() |
|
924 { |
|
925 CEglWindowSurface* self = new (ELeave) CEglWindowSurface; |
|
926 CleanupStack::PushL(self); |
|
927 self->ConstructL(); |
|
928 CleanupStack::Pop(self); |
|
929 return self; |
|
930 } |
|
931 |
|
932 |
|
933 void CEglWindowSurface::ConstructL() |
|
934 { |
|
935 } |
|
936 |
|
937 |
|
938 CEglWindowSurface::CEglWindowSurface() |
|
939 { |
|
940 } |
|
941 |
|
942 |
|
943 void CEglWindowSurface::DoCreateL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex) |
|
944 { |
|
945 iParamIndex = aIndex; |
|
946 iWindow = CWindow::NewL(aIndex, aOffset, aSizeIndex); |
|
947 iActualSize = iWindow->Window().Size(); |
|
948 |
|
949 CEglSurfaceBase::BaseCreateL(aIndex, EGL_WINDOW_BIT); |
|
950 |
|
951 iSurface = eglCreateWindowSurface(iDisplay, iConfig, &iWindow->Window(), NULL); |
|
952 if (iSurface == EGL_NO_SURFACE) |
|
953 { |
|
954 EGLint err = eglGetError(); |
|
955 RDebug::Printf("%s:%d: err = %x (%d x %d)", __FILE__, __LINE__, err, iActualSize.iWidth, iActualSize.iHeight); |
|
956 User::Leave(KErrNotSupported); |
|
957 } |
|
958 } |
|
959 |
|
960 |
|
961 CEglWindowSurface::~CEglWindowSurface() |
|
962 { |
|
963 Destroy(); |
|
964 eglReleaseThread(); |
|
965 delete iWindow; |
|
966 } |
|
967 |
|
968 |
|
969 TSurfaceId CEglWindowSurface::SurfaceId() const |
|
970 { |
|
971 // Default constructor for id sets it to a NULL-value, so if no window is created, we get |
|
972 // a defined surface id value that is invalid. |
|
973 TSurfaceId id; |
|
974 if (iWindow) |
|
975 { |
|
976 TSurfaceConfiguration surfConfig; |
|
977 iWindow->Window().GetBackgroundSurface(surfConfig); |
|
978 surfConfig.GetSurfaceId(id); |
|
979 } |
|
980 return id; |
|
981 } |
|
982 |
|
983 |
|
984 const TText *CEglWindowSurface::GetSurfaceTypeStr() const |
|
985 { |
|
986 return _S("CEglWindowSurface"); |
|
987 } |
|
988 |
|
989 |
|
990 CEglPBufferSurface::CEglPBufferSurface() |
|
991 { |
|
992 } |
|
993 |
|
994 |
|
995 CEglPBufferSurface::~CEglPBufferSurface() |
|
996 { |
|
997 Destroy(); |
|
998 eglReleaseThread(); |
|
999 } |
|
1000 |
|
1001 |
|
1002 CEglPBufferSurface* CEglPBufferSurface::NewL() |
|
1003 { |
|
1004 CEglPBufferSurface* self = new (ELeave) CEglPBufferSurface; |
|
1005 CleanupStack::PushL(self); |
|
1006 self->ConstructL(); |
|
1007 CleanupStack::Pop(self); |
|
1008 return self; |
|
1009 } |
|
1010 |
|
1011 |
|
1012 void CEglPBufferSurface::ConstructL() |
|
1013 { |
|
1014 } |
|
1015 |
|
1016 |
|
1017 const TText *CEglPBufferSurface::GetSurfaceTypeStr() const |
|
1018 { |
|
1019 return _S("CEglPBufferSurface"); |
|
1020 } |
|
1021 |
|
1022 |
|
1023 void CEglPBufferSurface::DoCreateL(TInt aIndex, const TPoint &/*aOffset*/, TInt aSizeIndex) |
|
1024 { |
|
1025 CEglSurfaceBase::BaseCreateL(aIndex, EGL_PBUFFER_BIT); |
|
1026 |
|
1027 EGLint attribs[] = |
|
1028 { |
|
1029 EGL_WIDTH, 0, |
|
1030 EGL_HEIGHT, 0, |
|
1031 EGL_NONE, |
|
1032 }; |
|
1033 if (KSurfaceParams[aIndex].iXSize & ELargestPossibleSurface) |
|
1034 { |
|
1035 iActualSize.iWidth = KSurfaceSizes[aSizeIndex].iWidth; |
|
1036 iActualSize.iHeight = KSurfaceSizes[aSizeIndex].iHeight; |
|
1037 } |
|
1038 else |
|
1039 { |
|
1040 iActualSize.iWidth = KSurfaceParams[aIndex].iXSize; |
|
1041 iActualSize.iHeight = KSurfaceParams[aIndex].iYSize; |
|
1042 } |
|
1043 for(TInt i = 0; attribs[i] != EGL_NONE; i += 2) |
|
1044 { |
|
1045 switch(attribs[i]) |
|
1046 { |
|
1047 case EGL_HEIGHT: |
|
1048 attribs[i+1] = iActualSize.iHeight; |
|
1049 break; |
|
1050 case EGL_WIDTH: |
|
1051 attribs[i+1] = iActualSize.iWidth; |
|
1052 break; |
|
1053 } |
|
1054 } |
|
1055 |
|
1056 iSurface = eglCreatePbufferSurface(iDisplay, iConfig, attribs); |
|
1057 if (iSurface == EGL_NO_SURFACE) |
|
1058 { |
|
1059 EGLint err = eglGetError(); |
|
1060 User::Leave(KErrNotSupported); |
|
1061 } |
|
1062 } |
|
1063 |
|
1064 |
|
1065 TSurfaceId CEglPBufferSurface::SurfaceId() const |
|
1066 { |
|
1067 SURF_ASSERT(0); // We shouldn't call this! |
|
1068 return TSurfaceId::CreateNullId(); |
|
1069 } |
|
1070 |
|
1071 TInt CEglPBufferSurface::SizeInBytes() const |
|
1072 { |
|
1073 // size of a pixel in bits. |
|
1074 EGLint size; |
|
1075 if (!eglGetConfigAttrib(iDisplay, iConfig, EGL_BUFFER_SIZE, &size)) |
|
1076 { |
|
1077 RDebug::Printf("Unable to get EGL_BUFFER_SIZE from config %d, err = %04x", iConfig, eglGetError()); |
|
1078 return 0; |
|
1079 } |
|
1080 |
|
1081 return (KSurfaceParams[iParamIndex].iXSize * KSurfaceParams[iParamIndex].iYSize * size) / 8; |
|
1082 } |
|
1083 |
|
1084 |
|
1085 // Factory function. |
|
1086 CSurface *CSurface::SurfaceFactoryL(TSurfaceType aSurfaceType) |
|
1087 { |
|
1088 switch(aSurfaceType) |
|
1089 { |
|
1090 case ESurfTypeRaw: |
|
1091 return CRawSurface::NewL(); |
|
1092 |
|
1093 case ESurfTypeEglWindow: |
|
1094 return CEglWindowSurface::NewL(); |
|
1095 |
|
1096 case ESurfTypeRawSingleBuffered: |
|
1097 return CRawSingleBufferSurface::NewL(); |
|
1098 |
|
1099 case ESurfTypePBuffer: |
|
1100 return CEglPBufferSurface::NewL(); |
|
1101 |
|
1102 default: |
|
1103 SURF_ASSERT(0); |
|
1104 return NULL; |
|
1105 } |
|
1106 } |