os/graphics/fbs/fontandbitmapserver/tfbs/tfbsoogm.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2009-2010 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: Test the operation of the Font and Bitmap Server's GOoM plug-in
    14 //
    15 
    16 
    17 #include <gdi.h>
    18 #include "tfbsoogm.h"
    19 
    20 
    21 
    22 const TInt KTFbsOogmFrameworkPause = 500000; // How long does this need to be in order to be reliable?
    23 const TInt KTFbsOogmImageSizeX = 2048;
    24 const TInt KTFbsOogmImageSizeY = 2048;
    25 
    26 
    27 void CTFbsOogm::RunTestCaseL( TInt aCurTestCase )
    28     {
    29     ( (CTFbsOogmStep*)iStep )->SetTestStepID( KUnknownSYMTestCaseIDName );
    30 
    31     switch( aCurTestCase )
    32         {
    33     case 1:
    34         ( (CTFbsOogmStep*)iStep )->SetTestStepID( _L("GRAPHICS-FBSERV-0675") );
    35 
    36         CacheClearanceAndLimitAdjustments();
    37         break;
    38 
    39     default:
    40         ( (CTFbsOogmStep*)iStep )->SetTestStepID( KNotATestSYMTestCaseIDName );
    41         ( (CTFbsOogmStep*)iStep )->CloseTMSGraphicsStep();
    42         TestComplete();
    43 
    44         break;
    45         }
    46 
    47     ( (CTFbsOogmStep*)iStep )->RecordTestResultL();
    48 
    49     }
    50 
    51 
    52 
    53 /**
    54  	@SYMTestCaseID
    55 	GRAPHICS-FBSERV-0675
    56 
    57 	@SYMTestCaseDesc
    58 	Tests the operation of Font and Bitmap server's  Out-Of-Graphics-Memory plugin.
    59 	ie Ensure that the hardware glyph cache is cleared in response to a low graphics 
    60 	memory notification, and that the cache's maximum size limit is reduced.
    61 
    62 
    63 	@SYMTestActions
    64 	Acquire the glyph cache's usage and other metrics.
    65 	
    66 	Populate the glyph-cache.
    67 
    68 	Acquire the glyph-cache's usage and other metrics.
    69 
    70 	Precipitate an Out-of-Graphics-Memory condition, triggering the GOOM monitor.
    71 
    72 	Acquire the glyph cache's usage and other metrics.
    73 
    74 	Ensure the glyph-cache has been cleared and its maximum limit reduced.
    75 
    76 	Precipitate a MemoryGood() call from the GOoM framework.
    77 
    78 	Establish that the cache-size limit has been reinstated.
    79 
    80 	@SYMTestExpectedResults
    81     The glyph-cache should be cleared in response to OoGM condition and its upper limit reduced.
    82 
    83     The Glyph-cache's upper limit should be reinstated in response to a memory-good notification.
    84  */
    85 void CTFbsOogm::CacheClearanceAndLimitAdjustments()
    86     {
    87     __UHEAP_MARK;
    88 
    89     RArray <RSgImage> sgImageArray;
    90     RSgDriver sgDriver;
    91     TInt err = sgDriver.Open();
    92 
    93     if( KErrNone != err )
    94         {
    95 		TEST( KErrNone == err );
    96 		INFO_PRINTF2( _L("SgDriver Open() returned error %d"), err );
    97 
    98         return;
    99         }
   100 
   101     if( (NULL == RFbsSession::GetSession()) )
   102          {
   103         if( KErrNone != RFbsSession::Connect() )
   104             {
   105  			TEST( -1 );
   106 			INFO_PRINTF1(_L("Failed to connect to FbServ"));
   107 
   108             goto CleanupAndGo;
   109             }
   110          }
   111 
   112 
   113 	// Establish the initial condition of the glyph-cache.
   114     TGlyphCacheMetrics initialGlyphCacheMetrics;
   115     err = RFbsSession::GetSession()->GetGlyphCacheMetrics( initialGlyphCacheMetrics );
   116     if( KErrNone != err )
   117         {
   118 		TEST( KErrNone == err );
   119 		INFO_PRINTF2( _L("GetGlyphCacheMetrics() returned error %d"), err );
   120 
   121         goto CleanupAndGo;
   122         }
   123 
   124 	// Check that initial conditions are as expected.
   125     // There was a test here for a cache-size of zero, but this was felt to be a hazardous assumption.
   126 	TEST( initialGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
   127     INFO_PRINTF4( _L("Initial iMaxCacheSizeInBytes %d iCacheSizeInBytes %d iGpuCacheSizeLimitIsMax %d "),
   128                       initialGlyphCacheMetrics.iMaxCacheSizeInBytes,
   129                       initialGlyphCacheMetrics.iCacheSizeInBytes,
   130                       initialGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
   131 
   132 
   133     TRAP( err, UseGpuL() ); // Populate the glyph cache then acquire its usage metrics.
   134     if( KErrNone != err )
   135         {
   136         TEST( KErrNone == err );
   137         INFO_PRINTF2( _L("UseGpuL() left with %d"), err );
   138 
   139         goto CleanupAndGo;
   140         }
   141 
   142 
   143     TGlyphCacheMetrics usageGlyphCacheMetrics;
   144     err = RFbsSession::GetSession()->GetGlyphCacheMetrics( usageGlyphCacheMetrics );
   145     if( KErrNone != err )
   146         {
   147 		TEST( KErrNone == err );
   148 		INFO_PRINTF2( _L("GetGlyphCacheMetrics() returned %d"), err );
   149 
   150         goto CleanupAndGo;
   151         }
   152 
   153     // Check that the glyph cache has been populated
   154     TEST( usageGlyphCacheMetrics.iCacheSizeInBytes > initialGlyphCacheMetrics.iCacheSizeInBytes);
   155     TEST( usageGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
   156     INFO_PRINTF4( _L("Usage iMaxCacheSizeInBytes %d iCacheSizeInBytes %d iGpuCacheSizeLimitIsMax %d "),
   157                        usageGlyphCacheMetrics.iMaxCacheSizeInBytes,
   158                        usageGlyphCacheMetrics.iCacheSizeInBytes,
   159                        usageGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
   160 
   161 
   162 
   163     // Precipitate the GOoM framework's call into the Plug-in's FreeRam() method.
   164     err = FillGraphicsMemoryWithImages( TSize(KTFbsOogmImageSizeX, KTFbsOogmImageSizeY), sgImageArray );
   165     if( KErrNoGraphicsMemory != err )
   166         {
   167 		TEST( KErrNoGraphicsMemory == err );
   168 		INFO_PRINTF2( _L("FillGraphicsMemoryWithImages() returned %d"), err );
   169 
   170         goto CleanupAndGo;
   171         }
   172 
   173 	// Await the GOOM framework's call into FbServ's OoGM plugin,
   174     // then establish the cache's usage and other metrics.
   175     User::After( KTFbsOogmFrameworkPause );
   176     TGlyphCacheMetrics postOogmGlyphCacheMetrics;
   177     err = RFbsSession::GetSession()->GetGlyphCacheMetrics( postOogmGlyphCacheMetrics );
   178 
   179     if( KErrNone != err )
   180         {
   181 		TEST( KErrNone == err );
   182 		INFO_PRINTF2( _L("GetGlyphCacheMetrics() returned %d"), err );
   183 
   184         goto CleanupAndGo;
   185         }
   186 
   187     // The cache should have been cleared and the maximum size limit reduced.
   188     TEST( 0 == postOogmGlyphCacheMetrics.iCacheSizeInBytes );
   189     TEST( !postOogmGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
   190     INFO_PRINTF4( _L("Post-Oogm iMaxCacheSizeInBytes %d iCacheSizeInBytes %d iGpuCacheSizeLimitIsMax %d "),
   191                         postOogmGlyphCacheMetrics.iMaxCacheSizeInBytes,
   192                         postOogmGlyphCacheMetrics.iCacheSizeInBytes,
   193                         postOogmGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
   194 
   195 
   196 
   197    // Remove the images. This should provoke a GOoM monitor call into the plug-in's MemoryGood().
   198     for ( TInt i = sgImageArray.Count()-1; i >= 0; --i )
   199         {
   200         sgImageArray[i].Close();
   201         }
   202     sgImageArray.Reset();
   203 
   204     // Await activity from the GOoM monitor
   205     User::After( KTFbsOogmFrameworkPause );
   206     TGlyphCacheMetrics reinstatedGlyphCacheMetrics;
   207     err = RFbsSession::GetSession()->GetGlyphCacheMetrics( reinstatedGlyphCacheMetrics );
   208     if( KErrNone != err )
   209         {
   210         TEST( KErrNone == err );
   211         INFO_PRINTF2( _L("GetGlyphCacheMetrics() returned error %d"), err );
   212 
   213         goto CleanupAndGo;
   214         }
   215 
   216     // Cache size limit should have been increased
   217     TEST( reinstatedGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
   218     INFO_PRINTF4( _L("After Mem Clear iMaxCacheSizeInBytes %d iCacheSizeInBytes %d iGpuCacheSizeLimitIsMax %d "),
   219                       reinstatedGlyphCacheMetrics.iMaxCacheSizeInBytes,
   220                       reinstatedGlyphCacheMetrics.iCacheSizeInBytes,
   221                       reinstatedGlyphCacheMetrics.iGpuCacheSizeLimitIsMax );
   222 
   223 
   224 
   225   CleanupAndGo:
   226     // Release any images before closing the array.
   227     // If the test was successful this should already be empty.
   228     for (TInt i = sgImageArray.Count()-1; i >= 0; --i)
   229         {
   230         sgImageArray[i].Close();
   231         }
   232 
   233     // Allow GOoM to make any pending adjustments before proceeding with any further tests.
   234     User::After( KTFbsOogmFrameworkPause );
   235     sgImageArray.Close();
   236     sgDriver.Close();
   237 
   238     __UHEAP_MARKEND;
   239     }
   240 
   241 
   242 
   243 CTFbsOogm::CTFbsOogm( CTestStep* aStep )
   244 : CTGraphicsBase(aStep)
   245     {
   246     }
   247 
   248 
   249 
   250 const TInt KNumGlyphCodesLatin = 96;
   251 /*
   252  Lookup table to convert from ascii code to
   253 glyph code for the Deja Vu family of fonts.
   254  */
   255 const TUint DejaVuASCIIToGlyphCode[] =
   256     {
   257     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   258     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   259     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   260     0, 0, 3, 4, 5, 6, 7, 8, 9, 10,
   261     11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
   262     21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
   263     31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
   264     41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
   265     51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
   266     61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
   267     71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
   268     81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
   269     91, 92, 93, 94, 95, 96, 97, 98,
   270     };
   271 
   272 
   273 
   274 void CTFbsOogm::ConstructL()
   275     {
   276     }
   277 
   278 
   279 CTFbsOogm::~CTFbsOogm()
   280     {
   281     RFbsSession::Disconnect();
   282     }
   283 
   284 
   285 
   286 /**
   287  Utility function to fill the GPU memory.
   288  */
   289 TInt CTFbsOogm::FillGraphicsMemoryWithImages( const TSize& aSize, RArray<RSgImage>& aImages )
   290     {
   291     TInt err = KErrNone;
   292 
   293     // Loop should terminate with KErrNoGraphicsMemory
   294     while( KErrNone == err )
   295         {
   296         RSgImage sgImage;
   297         err = sgImage.Create( TSgImageInfo(aSize, ESgPixelFormatA_8, ESgUsageBitOpenVgImage) );
   298         if( KErrNone == err )
   299             {
   300             err = aImages.Append( sgImage );
   301             }
   302         }
   303 
   304     INFO_PRINTF2( _L("Images created %d"), aImages.Count() );
   305     return err;
   306     }
   307 
   308 
   309 
   310 /**
   311  Utility function to populate the GPU with typeface glyphs.
   312  */
   313 void CTFbsOogm::UseGpuL()
   314     {
   315     _LIT( KTKASTypefaceName, "DejaVu Sans Condensed" );
   316 
   317     // Need to open one of these "in the context" of this process in order
   318     // to manipulate RSgImages. Even though we are only calling 'Open', 'Next' and 'Close' on
   319     // RFbsGlyphDataIterator
   320     RSgDriver sgDriver;
   321     User::LeaveIfError( sgDriver.Open() );
   322 
   323     // CFbsTypefaceStore seems to need an fbserv session open.
   324     if( (NULL == RFbsSession::GetSession()) )
   325      {
   326      User::LeaveIfError( RFbsSession::Connect() );
   327      }
   328 
   329     TUint* glyphCodesLatin = new(ELeave) TUint[ KNumGlyphCodesLatin ];
   330 
   331     for ( TInt ii = 0; ii < KNumGlyphCodesLatin; ++ii )
   332         {
   333         TUint asciiCode = ii+0x20; // ASCII characters from 0020 to 007F
   334         glyphCodesLatin[ii] = DejaVuASCIIToGlyphCode[asciiCode];
   335         }
   336 
   337     iTs = ( CFbsTypefaceStore* )CFbsTypefaceStore::NewL( NULL );
   338     User::LeaveIfError( iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont, TFontSpec(KTKASTypefaceName, 15)) );
   339 
   340     TInt iterErr = KErrNone;
   341     TInt iterNextErr = KErrNone;
   342 
   343     for( TInt arraySize = 1; (arraySize < KNumGlyphCodesLatin) && (iterErr == KErrNone); ++arraySize )
   344         {
   345         RFbsGlyphDataIterator iter;
   346         iterErr = iter.Open( *iFont, glyphCodesLatin, arraySize );
   347 
   348         if( KErrNone != iterErr )
   349             {
   350             continue;
   351             }
   352 
   353           for ( TInt index = 0; KErrNone == iterNextErr; iterNextErr = iter.Next(), ++index )
   354               {
   355               // Iterating through the glyphs should introduce them into the cache
   356              if(iter.GlyphCode() != glyphCodesLatin[index])
   357                 {
   358                  INFO_PRINTF4( _L("Wanted glyphcode %d, got %d"), arraySize, glyphCodesLatin[index], iter.GlyphCode() );
   359                 }
   360               }
   361 
   362         iterNextErr = KErrNone;
   363         iter.Close();
   364         }
   365 
   366     sgDriver.Close();
   367     }
   368 
   369 
   370 __CONSTRUCT_STEP__( FbsOogm )