os/graphics/graphicsdeviceinterface/directgdiadaptation/hwsrc/directgdidriverimpl.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 "directgdidriverimpl.h"
    17 #include "directgdiimagetargetimpl.h"
    18 #include "directgdiimagesourceimpl.h"
    19 #include "directgdiadapter.h"
    20 #include "directgdiimageref.h"
    21 #include "vgengine.h"
    22 #include "confighelper.h"
    23 #include <graphics/directgdiimagetarget.h>
    24 #include <graphics/sgresource.h>
    25 #include <fbs.h>
    26 #include <bitdev.h>
    27 
    28 #ifndef __WINS__
    29 // Static member variable
    30 XDirectGdiDriverProcessState CDirectGdiDriverImpl::gProcessState;
    31 #endif
    32 
    33 /**
    34 Handles an EGL failure. It may either set the passed-in TInt to a Symbian OS-mapped error code,
    35 or panic the specified panic code, depending on the egl failure. Done as a macro so the line number is reported.
    36 */
    37 #define HANDLE_EGL_ERROR(err, panic) \
    38 	{ \
    39 	const EGLint eglError = eglGetError(); \
    40 	if (eglError == EGL_BAD_ALLOC) \
    41 		err = KErrNoMemory; \
    42 	else if (eglError == EGL_CONTEXT_LOST) \
    43 		err = KErrDied; \
    44 	else if (eglError != EGL_SUCCESS) \
    45 		{ \
    46 		TBuf16<256> _message; \
    47 		_message.Format(_L16("EGL Error: %x\n"), eglError); \
    48 		GRAPHICS_LOGD_DEBUG(_message); \
    49 		GRAPHICS_ASSERT_DEBUG(eglError == EGL_SUCCESS, panic);	\
    50 		} \
    51 	}
    52 
    53 /**
    54 Populates the config hash map with matching EGL configs, based on the supported pixel types.
    55 
    56 @param aDisplay A valid EGL display to retrieve EGL configs for.
    57 
    58 @panic DGDIAdapter 24, if no suitable EGL configs are present (debug-only).
    59 @panic DGDIAdapter 25, if no exact matching EGL config can be found.
    60 @panic DGDIAdapter 29, if RSgImage::GetPixelFormats returns pixel count <= 0.
    61 
    62 @pre  EGL has been initialised by eglInitialize().
    63 @post The supported EGL configs are stored in the hash map.
    64 
    65 @return KErrNoError if successful, KErrNotReady if EGL was not initialised, otherwise one of the 
    66 system-wide error codes.
    67 */
    68 TInt CDirectGdiDriverImpl::InitializeEglConfigs(EGLDisplay aDisplay)
    69 	{
    70 #ifdef _DEBUG_DIRECTGDI
    71 	GRAPHICS_LOG_DEBUG("InitializeEglConfigs");
    72 #endif
    73 	TInt err = KErrNone;	
    74 	
    75 	// Get EGL configs upfront and store them in a hash map	
    76 	EGLint configSize = 0;
    77 	EGLConfig *configs = NULL;
    78 	
    79 	// Query RsgImage for the number of supported target pixel formats. Then we know how much memory should be 
    80 	// allocated to the pixelformats array.
    81 	TInt count = 0;
    82 	TSgImageInfo imageInfo;
    83 	imageInfo.iUsage = ESgUsageDirectGdiTarget;
    84 	imageInfo.iSizeInPixels = TSize(1,1);
    85 	TUidPixelFormat* pixelFormats = NULL;		
    86 	err = RSgImage::GetPixelFormats(imageInfo, NULL, count);
    87 	GRAPHICS_ASSERT_DEBUG(count > 0, EDirectGdiPanicNoValidPixelFormats);
    88 	
    89 	if (err == KErrNone)
    90 		{
    91 		pixelFormats = new TUidPixelFormat[count];			
    92 		if (pixelFormats == NULL)
    93 			{
    94 			err = KErrNoMemory;
    95 			}
    96 		}
    97 	
    98 	if (err == KErrNone)
    99 		{
   100 		err = RSgImage::GetPixelFormats(imageInfo, pixelFormats, count);		
   101 		if (!eglGetConfigs(aDisplay, configs, 0, &configSize) && configSize)
   102 			{
   103 			HANDLE_EGL_ERROR(err, EDirectGdiPanicNoAvailableConfigs);
   104 			}
   105 		}
   106 	
   107 	if (err == KErrNone)
   108 		{
   109 		configs = new EGLConfig[configSize];
   110 		if (configs == NULL)
   111 			{
   112 			err = KErrNoMemory;
   113 			}
   114 		}
   115 	
   116 	for (TInt i = 0; (i < count) && (err == KErrNone); ++i) 
   117 		{
   118 		// Finds a suitable config to map to this bitmap.
   119 		TInt selPixmapAttribs = TConfigHelper::MatchPixelType(pixelFormats[i]);
   120 		EGLint numConfigs = 0;
   121 		if (!eglChooseConfig(aDisplay, TConfigHelper::KSurfaceAttribs[selPixmapAttribs], configs, configSize, &numConfigs))
   122 			{
   123 			HANDLE_EGL_ERROR(err, EDirectGdiPanicNoMatchingConfig);
   124 			break;
   125 			}
   126 		GRAPHICS_ASSERT_ALWAYS(numConfigs >= 1, EDirectGdiPanicNoAvailableConfigs);
   127 		// Find an exact matching config from the available configs.
   128 		TInt match = TConfigHelper::GetSuitablePixmapConfigIndex(aDisplay, configs, numConfigs, selPixmapAttribs);
   129 		GRAPHICS_ASSERT_ALWAYS(match >= 0, EDirectGdiPanicNoMatchingConfig);
   130 		EGLConfig currentConfig = configs[match];
   131 
   132 		// Store this matching config and the pixel type in the hash map.
   133 		err = iPixelConfigMap.Insert(selPixmapAttribs, currentConfig);					
   134 		}		
   135 	
   136 	delete [] configs;		
   137 	delete [] pixelFormats;
   138 	
   139 	return err;
   140 	}
   141 
   142 /**
   143 Constructor to allocate memory to CDirectGdiDriverImpl object.
   144 
   145 @param aInternal On success, will store a pointer to the newly created CDirectGdiDriverImpl.
   146 @param aLibrary
   147 @return KErrNone if successful, otherwise one of the system-wide error codes.
   148 */
   149 TInt CDirectGdiDriverImpl::New(CDirectGdiDriverInternal*& aInternal, RLibrary aLibrary)
   150 	{
   151 	CDirectGdiDriverImpl* self = new CDirectGdiDriverImpl(aLibrary);
   152 	if(!self)
   153 		return KErrNoMemory;
   154 	TInt err = self->Construct();
   155 	if(err != KErrNone)
   156 		{
   157 		aInternal = NULL;
   158 		delete self;
   159 		return err;
   160 		}
   161 	aInternal = self;
   162 	return err;		
   163 	}
   164 
   165 /**
   166 Destructor - frees the memory for the hashmaps and the source and target arrays.
   167 
   168 @panic DGDIAdapter 45, if images are still in the source or target image array (debug-only).
   169 */
   170 CDirectGdiDriverImpl::~CDirectGdiDriverImpl()
   171 	{
   172 	// Check that there are no drawbles left in the drawable array
   173 	GRAPHICS_ASSERT_DEBUG(iSourceArray.Count() == 0, EDirectGdiPanicItemsLeftInImageArray);
   174 	GRAPHICS_ASSERT_DEBUG(iTargetArray.Count() == 0, EDirectGdiPanicItemsLeftInImageArray);
   175 	
   176 	iSourceArray.Close();
   177 	iTargetArray.Close();
   178 
   179 	delete iVgImageCache;
   180 	
   181 	THashMapIter<TInt, EGLContext> contextIter(iPixelContextMap);
   182 	const EGLContext* context = contextIter.NextValue();
   183 	while (context)
   184 		{
   185 		eglDestroyContext(iDisplay, *context);
   186 		context = contextIter.NextValue();		
   187 		}
   188 	iPixelContextMap.Close();
   189 	iPixelConfigMap.Close();
   190 	delete iGlyphImageStorage;
   191 
   192 	eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   193 	// This will terminate the display if it is the last driver.
   194 	ProcessState().CloseDriver(iDisplay); 
   195 	eglReleaseThread();
   196 	
   197 	SgDriver::Close();
   198 	}
   199 
   200 /**
   201 @see CDirectGdiDriver::Flush()
   202 */
   203 void CDirectGdiDriverImpl::Flush()
   204 	{
   205 	vgFlush();
   206 	}
   207 
   208 /**
   209  @see CDirectGdiDriver::Finish()
   210  */
   211 void CDirectGdiDriverImpl::Finish()
   212 	{
   213 	// Call eglWaitClient() instead of vgFinish() because MBX EGL implementation currently 
   214 	// does nothing with a vgFinish().
   215 	if (eglWaitClient() == EGL_FALSE)
   216 		{
   217 		TInt err = KErrNone;
   218 		HANDLE_EGL_ERROR(err, EDirectGdiPanicFinish);
   219 		SetError(err);
   220 		}
   221 
   222 	}
   223 
   224 /**
   225 @see CDirectGdiDriver::GetError()
   226 
   227 If no error has been reported explicitly, or SetError() has not been called, it will instead return
   228 the first (if any) OpenVG error to occur since GetError() was last called.
   229 */
   230 TInt CDirectGdiDriverImpl::GetError()
   231 	{
   232 	// Call vgGetError() even when iErrorCode is already set, so that any OpenVG error state is 
   233 	// cleared and not reported in future.
   234 	const TInt vgErrorCode = GetVgError();
   235 	
   236 	if (iErrorCode == KErrNone)
   237 		{
   238 		iErrorCode = vgErrorCode;
   239 		}
   240 	TInt error = iErrorCode;
   241 	iErrorCode = KErrNone;
   242 	return error;
   243 	}
   244 
   245 /**
   246 @see CDirectGdiDriver::CreateDrawableSource()
   247 
   248 For image resource creates a DirectGDI adaptation-specific resource from the given RSgDrawable resource so 
   249 it can be drawn using the DirectGDI rendering API. Creates an EGLImage, then a VGImage from the 
   250 passed RSgImage and associates the new source with these images. Sources that are successfully created 
   251 are added to an array of sources so that they can be closed and deleted correctly at a later stage.
   252 Note that an image source cannot be created before an image target has been created and activated.
   253 This is a limitation of OpenVG as a VG context must exist before an image source can be created.
   254 
   255 @param aHandleRet Handle of newly created drawable source, must be KNullHandle (is checked by generic driver).
   256 @param aSgDrawable The RSgDrawable object to use when creating the drawable source. An attempt is made to 
   257 match the pixel format of the new EGL surface with the pixel format of this RSgImage.
   258 
   259 @pre CDirectGdiDriver object has been initialised from the calling thread and a target has been activated.
   260      aHandleRet is KNullHandle.
   261 @post The DirectGDI adaptation-specific resource that is bound to the given 
   262 drawable resource is created and this handle is now associated with it. The reference 
   263 counter on the drawable resource is incremented. The CDirectGdiDriver for this thread 
   264 is now aware of and owns the adaptation-specific resource.
   265 
   266 @return KErrNone if successful, KErrArgument if the drawable resource is not valid, 
   267 KErrNotSupported if the drawable resource is not created with the type (KSgImageTypeUid), 
   268 otherwise one of the system-wide error codes.
   269 */
   270 TInt CDirectGdiDriverImpl::CreateDrawableSource(TInt& aHandleRet, const RSgDrawable& aSgDrawable)
   271 	{
   272 	TUid typeUid = aSgDrawable.DrawableType();
   273 	if(typeUid != KSgImageTypeUid)
   274 		{
   275 		return KErrNotSupported;
   276 		}
   277 	const RSgImage* image = reinterpret_cast<const RSgImage*>(&aSgDrawable); 
   278 	CDirectGdiImageSourceImpl* imageSource = NULL;
   279 	TInt err = CDirectGdiImageSourceImpl::New(imageSource, *this, *image);
   280 
   281 	if (err == KErrNone)
   282 		{
   283 		aHandleRet = reinterpret_cast<TInt>(imageSource);			
   284 		}
   285 	
   286 	return err;
   287 	}
   288 	
   289 /**
   290 @see CDirectGdiDriver::CreateDrawableSource()
   291 
   292 Destroys the DirectGDI adaptation-specific resource associated with this handle.
   293 Calling this method on a handle that is not associated with any DirectGDI specific 
   294 resource will do nothing. Once Close() is called, this handle can be reused. The handle
   295 is set to KNullHandle.
   296 
   297 @param 	aHandle A reference to a valid handle to a RDirectGdiDrawableSource object which is
   298         to be closed.
   299 
   300 @pre 	CDirectGdiDriver object has been initialised from the calling thread.
   301 @post 	The DirectGDI adaptation-specific resource associated with this handle will
   302 be destroyed (at any time preferred by the adaptation). This handle is no longer 
   303 associated with a DirectGDI adaptation-specific resource. The reference counter of 
   304 the underlying drawable resource is decremented. aHandle is set to KNullHandle.
   305 
   306 @panic DGDIAdapter 37, if an image source cannot be created from the passed handle.
   307 */
   308 void CDirectGdiDriverImpl::CloseDrawableSource(TInt& aHandle)
   309 	{	
   310 	CDirectGdiImageSourceImpl* imageSource = GetImageSourceFromHandle(aHandle);
   311 	GRAPHICS_ASSERT_ALWAYS(imageSource, EDirectGdiPanicCloseDrawableHandleFailure);		
   312 	
   313 	// Decrement the reference count on this image source. If it reaches zero, it will
   314 	// remove itself from the source array and delete itself.
   315 	imageSource->Close();
   316 	aHandle = KNullHandle;
   317 	}
   318 	
   319 
   320 /**
   321 @see CDirectGdiDriver::CreateImageTarget()
   322 
   323 Allocates and constructs a CDirectGdiImageTargetImpl object, and associates it with aHandleRet.
   324 
   325 @param  aHandleRet Handle of newly created Image Target, must be KNullHandle (is checked by generic driver).
   326 @param aSgImage The RSgImage to associate with the created image target. An attempt is made to match 
   327 the pixel format of the new EGL surface with the pixel format of this RSgImage.
   328 
   329 @pre 	CDirectGdiDriver object has been initialised from the calling thread.
   330 The image resource has been fully constructed and created with the correct usage 
   331 that allows it to be used as a DirectGDI target. aHandleRet is KNullHandle.
   332 
   333 @post 	The DirectGDI adaptation-specific resource that is bound to the given image 
   334 resource is created and this handle is now associated with it. The reference counter
   335 on the image resource is incremented. 
   336 
   337 @return KErrNone if successful, KErrArgument if the image resource is not valid, 
   338 KErrNotSupported if the image resource is not created with the correct 
   339 usage, otherwise one of the system-wide error codes.
   340 */
   341 TInt CDirectGdiDriverImpl::CreateImageTarget(TInt& aHandleRet, const RSgImage& aSgImage)
   342 	{		
   343 	CDirectGdiImageTargetImpl* imageTarget = NULL;
   344 	TInt err = CDirectGdiImageTargetImpl::New(imageTarget, *this, aSgImage, iPixelContextMap, iPixelConfigMap, iSharedContext);
   345 		
   346 	if (err == KErrNone)
   347 		{
   348 		// Return the handle to the newly created image target.
   349 		aHandleRet = reinterpret_cast<TInt>(imageTarget);					
   350 		}
   351 
   352 	return err;	
   353 	}
   354 
   355 /**
   356 Destroys the DirectGDI adaptation-specific resource associated with this handle. 
   357 Calling this method on a handle that is not associated with any DirectGDI adaptation-
   358 specific resource will do nothing. Once Close() is called, this handle can be reused.
   359 
   360 @param 	aHandle A handle to a RDirectGdiImageTarget object to be closed.
   361 
   362 @pre 	CDirectGdiDriver object has been initialised from the calling thread.
   363 
   364 @post 	The DirectGDI specific resource associated with this handle will be destroyed
   365 if the reference count falls to zero. This handle is no longer associated with 
   366 a DirectGDI specific resource. The reference counter of the underlying image 
   367 resource is decremented. aHandle is set to KNullHandle.
   368 
   369 @panic DGDIAdapter 37, if the image source associated with aHandle is NULL.
   370 */
   371 void CDirectGdiDriverImpl::CloseImageTarget(TInt& aHandle)
   372 	{	
   373 	CDirectGdiImageTargetImpl* imageTarget = GetImageTargetFromHandle(aHandle);
   374 	GRAPHICS_ASSERT_ALWAYS(imageTarget, EDirectGdiPanicCloseDrawableHandleFailure);	
   375 	
   376 	// Decrement the reference count on this image target. If the reference count reaches zero, 
   377 	// it is deleted and removed from the targets array.
   378 	imageTarget->Close();
   379 	aHandle = KNullHandle;
   380 	}
   381 
   382 /**
   383 Instantiates an adaptation-specific rendering engine.
   384 
   385 @param	aDirectGdiEngine Reference to instantiated engine.
   386 
   387 @pre 	CDirectGdiDriver object has been initialised from the calling thread.
   388 
   389 @return	KErrNone if the engine is constructed, else KErrNoMemory.
   390 */
   391 TInt CDirectGdiDriverImpl::CreateEngine(MDirectGdiEngine*& aDirectGdiEngine)
   392 	{
   393 	TInt result = KErrNone;
   394 	aDirectGdiEngine = new CVgEngine(*this);
   395 	if (aDirectGdiEngine == NULL)
   396 		{
   397 		result = KErrNoMemory;
   398 		}
   399 	return result;
   400 	}
   401 
   402 /**
   403 Unbinds target from rendering engine and marks it for deletion.
   404 NOTE: Currently this means just deleting the engine.
   405 
   406 @param	aDirectGdiEngine Engine to operate on.
   407 
   408 @pre CDirectGdiDriver object has been initialised from the calling thread.
   409 
   410 @panic DGDIAdapter 38, if the engine is NULL.
   411 */
   412 void CDirectGdiDriverImpl::DestroyEngine(MDirectGdiEngine* aDirectGdiEngine)
   413 	{
   414 	GRAPHICS_ASSERT_ALWAYS(aDirectGdiEngine, EDirectGdiPanicDestroyNullEngine);	
   415 	CVgEngine* actualEngine = static_cast<CVgEngine*>(aDirectGdiEngine);
   416 	delete actualEngine;
   417 	}
   418 
   419 /**
   420 The only extension interface supported by this implementation is MDirectGdiDriverCacheSize.
   421 
   422 @see CDirectGdiDriver::GetInterface()
   423  */
   424 TInt CDirectGdiDriverImpl::GetInterface(TUid aInterfaceId, TAny*& aInterface)
   425 	{
   426 	aInterface = NULL;
   427 	TInt err = KErrNone;
   428 	switch (aInterfaceId.iUid)
   429 		{
   430 		case KDirectGdiDriverCacheSizeUid:
   431 			{
   432 			aInterface = static_cast<MDirectGdiDriverCacheSize*>(this);
   433 			break;	
   434 			}		
   435 		default:
   436 			err = KErrExtensionNotSupported;
   437 			break;
   438 		}
   439 	return err;
   440 	}
   441 
   442 CDirectGdiDriverImpl::CDirectGdiDriverImpl(RLibrary aLibrary)
   443 	: CDirectGdiDriverInternal(aLibrary),
   444 	iDisplay(EGL_NO_DISPLAY)
   445 	{
   446 	}
   447 /**
   448 Performs the second phase of construction.
   449 
   450 @pre CDirectGdiDriver object has been initialised from the calling thread.
   451 @post EGL has been initialised. SgDriver has been opened.
   452 
   453 @panic DGDIAdapter 36, if eglGetDisplay() fails.
   454 @panic DGDIAdapter 35, if eglInitialize() fails.
   455 @panic DGDIAdapter 23, if eglBindAPI() fails.
   456 @return KErrNone if successful, KErrNotFound if no implementation of the Graphics Resource API is found,
   457         KErrNotSupported if the version of EGL is less than required (1.2), otherwise one of the 
   458         system-wide error codes.
   459 */
   460 TInt CDirectGdiDriverImpl::Construct()
   461 	{
   462 	TInt err = KErrNone;
   463 	iSharedContext = EGL_NO_CONTEXT;
   464 	
   465 	// First thing is to check whether the mutex for the Process State was successfully created.
   466 	// If not, it's a fatal error. If it is, we must increment the reference count on the mutex as 
   467 	// early as possible to make the creation/destruction of the display thread-safe. 
   468 	err = ProcessState().MutexCreationStatus();
   469 	if (err == KErrNone)
   470 		{
   471 		ProcessState().OpenDriver();
   472 		}
   473 
   474 	if (err == KErrNone)
   475 		{
   476 		err = SgDriver::Open();
   477 		}
   478 
   479 	if (err == KErrNone)
   480 		{
   481 		// Create display object
   482 		iDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   483 		GRAPHICS_ASSERT_ALWAYS(iDisplay != EGL_NO_DISPLAY, EDirectGdiPanicNoDisplay);			
   484 	
   485 		// Initialise the display.  If it is already initialised, EGL will return quickly.
   486 		EGLint major, minor;
   487 		if (!eglInitialize(iDisplay, &major, &minor))
   488 			{
   489 			iDisplay = EGL_NO_DISPLAY;
   490 			HANDLE_EGL_ERROR(err, EDirectGdiPanicInitializeDisplay);
   491 			}
   492 		else if (major < 1 || (major == 1 && minor < 2))
   493 			{
   494 			// Atleast EGL 1.2 needs to be available.
   495 			err = KErrNotSupported;
   496 			}
   497 		}
   498 
   499 	if (err == KErrNone)
   500 		{
   501 		// Let EGL know we will use it for OpenVG
   502 		if(!eglBindAPI(EGL_OPENVG_API))
   503 			{
   504 			HANDLE_EGL_ERROR(err, EDirectGdiPanicBindApi);
   505 			}
   506 		}
   507 
   508 	if (err == KErrNone)
   509 		{
   510 		iGlyphImageStorage = new CFontGlyphImageStorage(KDirectGdiAdapterDefaultMaxGlyphImageCacheSize);
   511 		if(!iGlyphImageStorage)
   512 			{
   513 			err = KErrNoMemory;
   514 			}
   515 		}
   516 
   517 	if (err == KErrNone)
   518 		{
   519 		iVgImageCache = new CVgImageCache(KDirectGdiAdapterDefaultMaxImageCacheSize);
   520 		if(!iVgImageCache)
   521 			{
   522 			err = KErrNoMemory;
   523 			}
   524 		}
   525 
   526 	if (err == KErrNone)
   527 		{
   528 		err = ProcessState().Initialize(iDisplay);
   529 		}
   530 
   531 	if (err == KErrNone)
   532 		{
   533 		err = InitializeEglConfigs(iDisplay);
   534 		}
   535 	
   536 	return err;
   537 	}
   538 
   539 /**
   540 @see CDirectGdiDriver::SetError()
   541 
   542 In the event that OpenVG's error state has been set, it will be used as the driver's error state,
   543 overriding aErr.  
   544 
   545 @param aErr The error code to be set.
   546 @pre  CDirectGdiDriver object has been initialised from the calling thread.
   547 @post The error state is set to the current OpenVG error state, otherwise aErr, if the current error state
   548       is empty.
   549 */
   550 void CDirectGdiDriverImpl::SetError(TInt aErr)
   551 	{
   552 	if(	iErrorCode == KErrNone )
   553 		{
   554 		iErrorCode = GetVgError();
   555 		if (iErrorCode == KErrNone)
   556 			{
   557 			iErrorCode = aErr;
   558 			}
   559 		}
   560 	}
   561 
   562 /**
   563 Static function. Converts the current OpenVG error state (if any) to a standard Symbian error code.
   564 
   565 @panic DGDIAdapter 64, if the error code received from OpenVG is due to misuse of OpenVG rather
   566        than a runtime error.
   567 @return KErrGeneral if the OpenVG error code not recognised, otherwise a system-wide error 
   568 code converted from the OpenVG error code.
   569 */
   570 TInt CDirectGdiDriverImpl::GetVgError()
   571 	{
   572 	TInt error = KErrGeneral;
   573 	switch(vgGetError())
   574 		{
   575 		case VG_NO_ERROR:
   576 			error = KErrNone;
   577 			break;
   578 		case VG_BAD_HANDLE_ERROR:
   579 			error = KErrBadHandle;
   580 			break;
   581 		case VG_ILLEGAL_ARGUMENT_ERROR:
   582 			error = KErrArgument;
   583 			break;
   584 		case VG_OUT_OF_MEMORY_ERROR:
   585 			error = KErrNoMemory;
   586 			break;
   587 		default:
   588 			// Any other error is due to DirectGDI using OpenVG incorrectly somewhere.
   589 			GRAPHICS_PANIC_DEBUG(EDirectGdiPanicVgError);
   590 		}	
   591 	return error;
   592 	}
   593 
   594 /**
   595 Sets the current engine as the most recent engine which has been activated.
   596 
   597 @param 	aCurrentEngine The pointer to the most recent engine.
   598 */
   599 void CDirectGdiDriverImpl::SetCurrentEngine(CVgEngine* aCurrentEngine)
   600 	{
   601 	iCurrentEngine = aCurrentEngine;
   602 	}
   603 
   604 /**
   605 Checks whether the given engine is current or not, so that the OpenVG state can be reset.
   606 
   607 @param 	aCurrentEngine The pointer to an engine.
   608 @return ETrue if it is the current engine, else EFalse.
   609 */
   610 TBool CDirectGdiDriverImpl::IsCurrentEngine(const CVgEngine* aCurrentEngine) const
   611 	{
   612 	return (iCurrentEngine == aCurrentEngine);
   613 	}
   614 
   615 /**
   616 Checks whether this target is current or not, so that the EGL state can be reset.
   617 
   618 @param 	aCurrentTarget The pointer to a target.
   619 @return ETrue if it is the current target, else EFalse.
   620 */
   621 TBool CDirectGdiDriverImpl::IsCurrentTarget(const CDirectGdiImageTargetImpl* aCurrentTarget) const
   622 	{
   623 	return (iCurrentTarget == aCurrentTarget);
   624 	}
   625 
   626 /**
   627 Sets the current target as the most recent target which has been activated.
   628 
   629 @param 	aCurrentTarget The pointer to the most recent target.
   630 */
   631 void CDirectGdiDriverImpl::SetCurrentTarget(CDirectGdiImageTargetImpl* aCurrentTarget)
   632 	{
   633 	iCurrentTarget = aCurrentTarget;
   634 	}
   635 
   636 /**
   637 Activates the specified target and increments its reference count as it can be shared across many 
   638 DirectGDI contexts.
   639 
   640 @param aRenderingTarget The target object which is to be activated.
   641 */
   642 void CDirectGdiDriverImpl::Activate(CDirectGdiImageTargetImpl* aRenderingTarget)
   643 	{
   644 	// Reactivate() does the same activation
   645 	Reactivate(aRenderingTarget);
   646 	aRenderingTarget->Open();
   647 	}
   648 
   649 /**
   650 Reactivates the specified target, without affecting its reference count.
   651 
   652 @param aRenderingTarget The target to be reactivated.
   653 
   654 @panic DGDIAdapter 2, if eglGetError() returns an error we can't handle.
   655 */
   656 void CDirectGdiDriverImpl::Reactivate(CDirectGdiImageTargetImpl* aRenderingTarget)
   657 	{
   658 	if(!aRenderingTarget->Activate())
   659 		{
   660 		TInt error = KErrNone;
   661 		HANDLE_EGL_ERROR(error, EDirectGdiPanicUnexpectedError);
   662 		if(error == KErrNoMemory)
   663 			{
   664 			SetError(error);
   665 			}
   666 		// Can check here whether error == KErrDied, which signifies an EGL_CONTEXT_LOST error.
   667 		// due to a power management event.  Then need to destroy and recreate all EGLContexts used.
   668 		// This is not implemented as the EGL used with this reference adaptation does not produce this error.
   669 		// Following pseudocode will achieve this:
   670 		// 1. For each context stored in iPixelMapContext:
   671 		// 1a. Destroy context.
   672 		// 1b. Create replacement context with same parameters.
   673 		// 1c. Search through all rendering targets replacing the context stored (if it matches with the one just destroyed) with the new one.
   674 		// 2. Try activating the rendering target again.
   675 		}
   676 	}
   677 
   678 /**
   679 Deactivates the target if it was the current target, and decrements its reference count as it can 
   680 be shared across many DirectGDI contexts.
   681 
   682 @param 	aRenderingTarget The target object which you want to deactivate.
   683 */
   684 void CDirectGdiDriverImpl::Deactivate(CDirectGdiImageTargetImpl* aRenderingTarget)
   685 	{			
   686 	aRenderingTarget->Close();
   687 	}
   688 
   689 /**
   690 Helper function for removing a pointer to a CDirectGdiImageRef object from the source image array.
   691 @param aImage A pointer to a CDirectGdiImageRef source object.
   692 @return KErrNone if successful, KErrNotFound if no suitable object pointer can be found, 
   693 otherwise one of the other system wide error codes.
   694  */
   695 TInt CDirectGdiDriverImpl::UnregisterSourceImage(const CDirectGdiImageSourceImpl& aImage)
   696 	{
   697 	TInt index = -1;
   698 	TInt err = iSourceArray.FindInAddressOrder(&aImage, index);
   699 	if (err == KErrNone)
   700 		{
   701 		iSourceArray.Remove(index);		
   702 		iSourceArray.GranularCompress();
   703 		}
   704 	
   705 	return err;
   706 	}
   707 
   708 /**
   709 Helper function for removing a pointer to a CDirectGdiImageRef object from the target image array.
   710 @param aImage A pointer to a CDirectGdiImageRef source object.
   711 @return KErrNone if successful, KErrNotFound if no suitable object pointer can be found, 
   712 otherwise one of the other system wide error codes.
   713  */
   714 TInt CDirectGdiDriverImpl::UnregisterTargetImage(const CDirectGdiImageTargetImpl& aImage)
   715 	{
   716 	TInt index = -1;
   717 	TInt err = iTargetArray.FindInAddressOrder(&aImage, index);
   718 	if (err == KErrNone)
   719 		{
   720 		iTargetArray.Remove(index);		
   721 		iTargetArray.GranularCompress();
   722 		}	
   723 	
   724 	return err;
   725 	}
   726 
   727 /** 
   728 Helper function to convert a handle for a RDirectGdiDrawableSource object to a CDirectGdiImageSourceImpl 
   729 object. In debug builds, it also checks that the image source was actually created by this driver and 
   730 exists in the array of image sources.
   731 
   732 @param aHandle A valid handle to a RDirectGdiDrawableSource object.
   733 @return A pointer to a CDirectGdiImageSourceImpl object that the handle represents.
   734 */
   735 CDirectGdiImageSourceImpl* CDirectGdiDriverImpl::GetImageSourceFromHandle(TInt aHandle) const
   736 	{
   737 #ifdef _DEBUG
   738 	CheckSourceIsValid(aHandle);
   739 #endif // _DEBUG
   740 	
   741 	CDirectGdiImageSourceImpl* source = reinterpret_cast<CDirectGdiImageSourceImpl*>(aHandle);
   742 	return source;
   743 	}
   744 
   745 /** 
   746 Helper function to convert a handle for a RDirectGdiImageTarget object to a CDirectGdiImageTargetImpl 
   747 object. In debug builds, it also checks that the image target was actually created by this driver and 
   748 exists in the array of image target.
   749 
   750 @param aHandle A valid handle to a RDirectGdiImageTarget object.
   751 @return A pointer to a CDirectGdiImageTargetImpl object that the handle represents.
   752 */
   753 CDirectGdiImageTargetImpl* CDirectGdiDriverImpl::GetImageTargetFromHandle(TInt aHandle) const
   754 	{
   755 #ifdef _DEBUG
   756 	CheckTargetIsValid(aHandle);
   757 #endif // _DEBUG
   758 	
   759 	CDirectGdiImageTargetImpl* target = reinterpret_cast<CDirectGdiImageTargetImpl*>(aHandle);
   760 	return target;
   761 	}
   762 
   763 /**
   764 Allows the engine to check whether a resource is an image source or not, given its handle. 
   765 If the image is an image source, it will be in the array of image sources.
   766 
   767 @param aHandle The handle to check for being an image source.
   768 @return ETrue if the passed handle is for an image source, EFalse otherwise.
   769  */
   770 TBool CDirectGdiDriverImpl::IsImageSource(TInt aHandle) const
   771 	{
   772 	CDirectGdiImageRef* source = reinterpret_cast<CDirectGdiImageRef*>(aHandle);
   773 	TInt index = -1;	
   774 	return (iSourceArray.FindInAddressOrder(source, index) == KErrNone);
   775 	}
   776 
   777 #ifdef _DEBUG
   778 /**
   779 Debug-only helper function to check that a source object has been created by this driver.
   780 If it has been created by this driver it will exist in the source array.
   781 
   782 @panic DGDIAdapter 32, if the source can not be found in the source array.
   783 */
   784 void CDirectGdiDriverImpl::CheckSourceIsValid(TInt aHandle) const
   785 	{
   786 	// Debug only check to make sure the handle exists in the array of source objects 	
   787 	// that have been created by this driver
   788 	CDirectGdiImageRef* source = reinterpret_cast<CDirectGdiImageRef*>(aHandle);
   789 	TInt index = -1;	
   790 	TInt err = iSourceArray.FindInAddressOrder(source, index);
   791 	GRAPHICS_ASSERT_ALWAYS(err == KErrNone, EDirectGdiPanicResourceHandleNotFound);
   792 	}
   793 
   794 /**
   795 Debug-only helper function to check that a target object has been created by this driver.
   796 If it has been created by this driver it will exist in the target array.
   797 
   798 @panic DGDIAdapter 32, if the target is not found in the target array.
   799  */
   800 void CDirectGdiDriverImpl::CheckTargetIsValid(TInt aHandle) const
   801 	{
   802 	// Debug only check to make sure the handle exists in the array of target objects 	
   803 	// that have been created by this driver
   804 	CDirectGdiImageRef* target = reinterpret_cast<CDirectGdiImageRef*>(aHandle);
   805 	TInt index = -1;	
   806 	TInt err = iTargetArray.FindInAddressOrder(target, index);
   807 	GRAPHICS_ASSERT_ALWAYS(err == KErrNone, EDirectGdiPanicResourceHandleNotFound);
   808 	}
   809 #endif // _DEBUG
   810 
   811 // VGImage cache APIs
   812 
   813 /**
   814 @see CVgImageCache::GetVgImageFromCache()
   815  */
   816 VGImage CDirectGdiDriverImpl::GetVgImageFromCache(const CFbsBitmap& aBitmap, const TPoint& aOrigin) const
   817 	{
   818 	return iVgImageCache->GetVgImageFromBitmap(aBitmap, aOrigin);
   819 	}
   820 
   821 /**
   822 @see CVgImageCache::AddImage()
   823  */
   824 TBool CDirectGdiDriverImpl::AddVgImageToCache(const CFbsBitmap& aBitmap, VGImage& aImage, const TPoint& aOrigin)
   825 	{
   826 	return iVgImageCache->AddImage(aBitmap, aImage, aOrigin);
   827 	}
   828 
   829 /**
   830 Gets the VGImage cache.
   831 @return The VGImage cache.
   832 */
   833 CVgImageCache* CDirectGdiDriverImpl::VgImageCache() const
   834 	{
   835 	return iVgImageCache;
   836 	}
   837 
   838 /**
   839 Gets the Glyph image storage.
   840 @return The Glyph image storage.
   841 */
   842 CFontGlyphImageStorage* CDirectGdiDriverImpl::FontGlyphImageStorage() const
   843 	{
   844 	return iGlyphImageStorage;
   845 	}
   846 
   847 /**
   848 Creates VG images which will be used to draw glyphs if the system runs out of memory
   849 */
   850 TInt CDirectGdiDriverImpl::PreAllocateFontGlyphImages()
   851 	{
   852 	TInt res = KErrNotReady;
   853 	if(iGlyphImageStorage)
   854 		{
   855 		res = iGlyphImageStorage->PreAllocateImages();
   856 		if(res == KErrNoMemory)
   857 			{//try to clean bitmap cache
   858 			iVgImageCache->ResetCache();
   859 			res = iGlyphImageStorage->PreAllocateImages();
   860 			if(res == KErrNoMemory)
   861 				{//try to clean glyph image cache
   862 				iGlyphImageStorage->CleanGlyphImageCache();
   863 				res = iGlyphImageStorage->PreAllocateImages();
   864 				}
   865 			}
   866 		}
   867 	return res;	
   868 	}
   869 
   870 /** 
   871 Registers the image source with this driver, by adding it to a list of internal image sources.
   872 @param aImage The image to register.
   873 @return KErrNone if successful, otherwise on of the system-wide error codes.
   874 */ 
   875 TInt CDirectGdiDriverImpl::RegisterSourceImage(const CDirectGdiImageSourceImpl& aImage)
   876 	{
   877 	return iSourceArray.InsertInAddressOrder(&aImage);
   878 	}
   879 
   880 /** 
   881 Registers the image target with this driver, by adding it to a list of internal image targets.
   882 @param aImage The image to register.
   883 @return KErrNone if successful, otherwise on of the system-wide error codes.
   884 */ 
   885 TInt CDirectGdiDriverImpl::RegisterTargetImage(const CDirectGdiImageTargetImpl& aImage)
   886 	{
   887 	return iTargetArray.InsertInAddressOrder(&aImage);
   888 	}
   889 
   890 /** 
   891 @see MDirectGdiDriverCacheSize::SetMaxImageCacheSize()
   892  */
   893 TInt CDirectGdiDriverImpl::SetMaxImageCacheSize(TInt aSize)
   894 	{
   895 	return iVgImageCache->SetMaxCacheSize(aSize);
   896 	}
   897 
   898 /** 
   899 @see MDirectGdiDriverCacheSize::MaxImageCacheSize()
   900  */
   901 TInt CDirectGdiDriverImpl::MaxImageCacheSize() const
   902 	{
   903 	return iVgImageCache->MaxCacheSize();
   904 	}
   905 
   906 /** 
   907 @see MDirectGdiDriverCacheSize::SetMaxGlyphCacheSize()
   908  */
   909 TInt CDirectGdiDriverImpl::SetMaxGlyphCacheSize(TInt aSize)
   910 	{
   911 	return iGlyphImageStorage->SetMaxGlyphCacheSize(aSize);
   912 	}
   913 
   914 /** 
   915 @see MDirectGdiDriverCacheSize::MaxGlyphCacheSize()
   916  */
   917 TInt CDirectGdiDriverImpl::MaxGlyphCacheSize() const
   918 	{
   919 	return iGlyphImageStorage->MaxGlyphCacheSize();
   920 	}