graphicsresourceservices/graphicsresourceadaptation/src/sgdriverimpl.cpp
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     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 <e32math.h>
       
    17 #include "sgdriverimpl.h"
       
    18 #include "sgimageimpl.h"
       
    19 #include "sgimagecollectionimpl.h"
       
    20 
       
    21 
       
    22 TInt SgAlignedDataStride(TInt aWidthInPixels, TUidPixelFormat aPixelFormat)
       
    23 	{
       
    24 #if defined(SYMBIAN_GRAPHICS_USE_MBX)
       
    25 	// MBX requires 2^n stride. 
       
    26 	for (TInt width = 8; width & KMaxTInt; width <<= 1)
       
    27 		{
       
    28 		if (width >= aWidthInPixels)
       
    29 			{
       
    30 			aWidthInPixels = width;
       
    31 			break;
       
    32 			}
       
    33 		}
       
    34 #elif defined(SYMBIAN_GRAPHICS_USE_SGX)
       
    35 	// SGX requires a 32 pixel alignment. 
       
    36 	aWidthInPixels = (aWidthInPixels + 31) & ~31;
       
    37 #endif
       
    38 	return Align4(SgMinDataStride(aWidthInPixels, aPixelFormat));
       
    39 	}
       
    40 
       
    41 
       
    42 TInt SgOffsetToFirstBuffer(TInt aMetaDataSize)
       
    43 	{
       
    44 #if defined(SYMBIAN_GRAPHICS_USE_MBX) || defined(SYMBIAN_GRAPHICS_USE_SGX)
       
    45 	return (aMetaDataSize + 127) & ~127;
       
    46 #else
       
    47 	return Align4(aMetaDataSize);
       
    48 #endif
       
    49 	}
       
    50 
       
    51 
       
    52 TInt SgOffsetBetweenBuffers(TInt aDataStride, TInt aScanLineCount)
       
    53 	{
       
    54 #if defined(SYMBIAN_GRAPHICS_USE_MBX)
       
    55 	for (TInt count = 16; count & KMaxTInt; count <<= 1)
       
    56 		{
       
    57 		if (count >= aScanLineCount)
       
    58 			{
       
    59 			aScanLineCount = count;
       
    60 			break;
       
    61 			}
       
    62 		}
       
    63 #endif
       
    64 	return aDataStride * aScanLineCount;
       
    65 	}
       
    66 
       
    67 
       
    68 TBool SgIsValidImageInfo(const TSgImageInfo& aInfo)
       
    69 	{
       
    70 	return aInfo.iSizeInPixels.iWidth > 0 && aInfo.iSizeInPixels.iHeight > 0
       
    71 		&& (aInfo.iUsage & ESgUsageScreenSource ? aInfo.iScreenId >= KSgScreenIdMain : aInfo.iScreenId >= KSgScreenIdAny)
       
    72 		&& (aInfo.iUserAttributes ? aInfo.iUserAttributeCount > 0 : aInfo.iUserAttributeCount == 0);
       
    73 	}
       
    74 
       
    75 
       
    76 TBool SgIsMutableImage(const TSgImageInfo& aInfo)
       
    77 	{
       
    78 	return (aInfo.iCpuAccess & ESgCpuAccessWritable) || (aInfo.iUsage & KSgUsageAllTargets);
       
    79 	}
       
    80 
       
    81 
       
    82 TBool SgIsCachedImage(const TSgImageInfo& aInfo)
       
    83 	{
       
    84 #ifdef SYMBIAN_GRAPHICS_USE_GPU
       
    85 #ifdef SYMBIAN_GRAPHICS_USE_CACHE
       
    86 	return aInfo.iCpuAccess != ESgCpuAccessNone;
       
    87 #else
       
    88 	(void)aInfo;
       
    89 	return EFalse;
       
    90 #endif
       
    91 #else
       
    92 	(void)aInfo;
       
    93 	return ETrue;
       
    94 #endif
       
    95 	}
       
    96 
       
    97 
       
    98 // TSgPixelFormatTableEntry
       
    99 
       
   100 TBool TSgPixelFormatTableEntry::IsMatch(const TSgImageInfo& aInfo) const
       
   101 	{
       
   102 	return iPixelFormat == aInfo.iPixelFormat
       
   103 		&& !(~iUsage & aInfo.iUsage)
       
   104 		&& !(~iCpuAccess & aInfo.iCpuAccess)
       
   105 		&& (iScreenId == KSgScreenIdAny || iScreenId == aInfo.iScreenId);
       
   106 	}
       
   107 
       
   108 
       
   109 TBool TSgPixelFormatTableEntry::IsMatchIgnoringPixelFormat(const TSgImageInfo& aInfo) const
       
   110 	{
       
   111 	return !(~iUsage & aInfo.iUsage)
       
   112 		&& !(~iCpuAccess & aInfo.iCpuAccess)
       
   113 		&& (iScreenId == KSgScreenIdAny || iScreenId == aInfo.iScreenId);
       
   114 	}
       
   115 
       
   116 
       
   117 TBool TSgPixelFormatTableEntry::IsMatchIgnoringUsage(const TSgImageInfo& aInfo) const
       
   118 	{
       
   119 	return iPixelFormat == aInfo.iPixelFormat
       
   120 		&& !(~iCpuAccess & aInfo.iCpuAccess)
       
   121 		&& (iScreenId == KSgScreenIdAny || iScreenId == aInfo.iScreenId);
       
   122 	}
       
   123 
       
   124 
       
   125 // XSgBase
       
   126 
       
   127 XSgBase::~XSgBase()
       
   128 	{
       
   129 	__ASSERT_DEBUG(iDriverImpl.IsMutexHeld(), Panic(ESgPanicMutexNotHeld));
       
   130 	__ASSERT_DEBUG(iRefCount == 0, Panic(ESgPanicBadReferenceCount));
       
   131 	}
       
   132 
       
   133 
       
   134 void XSgBase::Delete()
       
   135 	{
       
   136 	XSgDriverImpl& driverImpl = iDriverImpl;
       
   137 	this->~XSgBase();
       
   138 	driverImpl.Free(this);
       
   139 	}
       
   140 
       
   141 
       
   142 // XSgDriverImpl
       
   143 
       
   144 TInt XSgDriverImpl::Construct()
       
   145 	{
       
   146 	TInt err = iMutex.CreateLocal();
       
   147 	if (err != KErrNone)
       
   148 		{
       
   149 		return err;
       
   150 		}
       
   151 	err = iSurfaceManager.Open();
       
   152 	if (err != KErrNone)
       
   153 		{
       
   154 		return err;
       
   155 		}
       
   156 	return ConstructPixelFormatTable();
       
   157 	}
       
   158 
       
   159 
       
   160 XSgDriverImpl::~XSgDriverImpl()
       
   161 	{
       
   162 	__ASSERT_DEBUG(iImages.Count() == 0, Panic(ESgPanicUnclosedResources));
       
   163 	__ASSERT_DEBUG(iImageCollections.Count() == 0, Panic(ESgPanicUnclosedResources));
       
   164 	iMutex.Close();
       
   165 	iSurfaceManager.Close();
       
   166 	RHeap* prevHeap = User::SwitchHeap(iHeap);
       
   167 	iPixelFormatTable.Close();
       
   168 	iLastPixelFormats.Close();
       
   169 	User::SwitchHeap(prevHeap);
       
   170 	}
       
   171 
       
   172 
       
   173 void XSgDriverImpl::Delete()
       
   174 	{
       
   175 	RHeap* heap = iHeap;
       
   176 	this->~XSgDriverImpl();
       
   177 	heap->Free(this);
       
   178 	__ASSERT_DEBUG(heap->Count() == 0, Panic(ESgPanicUnclosedResources));
       
   179 	heap->Close();
       
   180 	}
       
   181 
       
   182 
       
   183 TInt XSgDriverImpl::MapSurface(const TSurfaceId& aSurfaceId, RChunk& aChunk)
       
   184 	{
       
   185 	RChunk chunk;
       
   186 	TInt err = iSurfaceManager.MapSurface(aSurfaceId, chunk);
       
   187 	if (err != KErrNone)
       
   188 		{
       
   189 		return err;
       
   190 		}
       
   191 	aChunk = chunk;
       
   192 	err = aChunk.Duplicate(RThread()); // Get a process-wide handle
       
   193 	chunk.Close();
       
   194 	return err;
       
   195 	}
       
   196 
       
   197 
       
   198 TArray<TSgPixelFormatTableEntry> XSgDriverImpl::PixelFormatTable() const
       
   199 	{
       
   200 	return iPixelFormatTable.Array();
       
   201 	}
       
   202 
       
   203 
       
   204 TInt XSgDriverImpl::CanCreateImage(const TSgImageInfo& aInfo) const
       
   205 	{
       
   206 	__ASSERT_DEBUG(SgIsValidImageInfo(aInfo), Panic(ESgPanicBadImageInfo));
       
   207 	if (aInfo.iSizeInPixels.iWidth > KMaxTInt16 / 2 || aInfo.iSizeInPixels.iHeight > KMaxTInt16 / 2)
       
   208 		{
       
   209 		return KErrTooBig;
       
   210 		}
       
   211 	TArray<TSgPixelFormatTableEntry> pixelFormatTable = PixelFormatTable();
       
   212 	TInt n = pixelFormatTable.Count();
       
   213 	for (TInt i = 0; i < n; ++i)
       
   214 		{
       
   215 		if (pixelFormatTable[i].IsMatch(aInfo))
       
   216 			{
       
   217 			return SgMinDataStride(aInfo.iSizeInPixels.iWidth, aInfo.iPixelFormat) > 0 ? KErrNone : KErrNotSupported;
       
   218 			}
       
   219 		}
       
   220 	return KErrNotSupported;
       
   221 	}
       
   222 
       
   223 
       
   224 TInt XSgDriverImpl::GetPixelFormats(const TSgImageInfo& aInfo, TUidPixelFormat* aPixelFormats, TInt& aCount)
       
   225 	{
       
   226 	if (!SgIsValidImageInfo(aInfo) || (aPixelFormats && aCount < 0))
       
   227 		{
       
   228 		return KErrArgument;
       
   229 		}
       
   230 	iMutex.Wait();
       
   231 	if (aInfo.iSizeInPixels != iLastSizeInPixels
       
   232 		|| aInfo.iUsage != iLastUsage
       
   233 		|| aInfo.iCpuAccess != iLastCpuAccess
       
   234 		|| aInfo.iScreenId != iLastScreenId)
       
   235 		{
       
   236 		iLastSizeInPixels = aInfo.iSizeInPixels;
       
   237 		iLastUsage = aInfo.iUsage;
       
   238 		iLastCpuAccess = aInfo.iCpuAccess;
       
   239 		iLastScreenId = aInfo.iScreenId;
       
   240 		RHeap* prevHeap = User::SwitchHeap(iHeap);
       
   241 		iLastPixelFormats.Reset();
       
   242 		User::SwitchHeap(prevHeap);
       
   243 		TArray<TSgPixelFormatTableEntry> pixelFormatTable = PixelFormatTable();
       
   244 		TInt n = pixelFormatTable.Count();
       
   245 		for (TInt i = 0; i < n; ++i)
       
   246 			{
       
   247 			const TSgPixelFormatTableEntry& entry = pixelFormatTable[i];
       
   248 			if (entry.IsMatchIgnoringPixelFormat(aInfo) && iLastPixelFormats.Find(entry.iPixelFormat) == KErrNotFound)
       
   249 				{
       
   250 				User::SwitchHeap(iHeap);
       
   251 				TInt err = iLastPixelFormats.Append(entry.iPixelFormat);
       
   252 				User::SwitchHeap(prevHeap);
       
   253 				if (err != KErrNone)
       
   254 					{
       
   255 					iLastSizeInPixels = TSize(0, 0);
       
   256 					iLastUsage = ESgUsageNone;
       
   257 					iLastCpuAccess = ESgCpuAccessNone;
       
   258 					iLastScreenId = KSgScreenIdMain;
       
   259 					User::SwitchHeap(iHeap);
       
   260 					iLastPixelFormats.Reset();
       
   261 					User::SwitchHeap(prevHeap);
       
   262 					iMutex.Signal();
       
   263 					return err;
       
   264 					}
       
   265 				}
       
   266 			}
       
   267 		}
       
   268 	TInt err = KErrNone;
       
   269 	if (aPixelFormats)
       
   270 		{
       
   271 		TInt n = Min(aCount, iLastPixelFormats.Count());
       
   272 		for (TInt i = 0; i < n; ++i)
       
   273 			{
       
   274 			aPixelFormats[i] = iLastPixelFormats[i];
       
   275 			}
       
   276 		if (aCount < iLastPixelFormats.Count())
       
   277 			{
       
   278 			err = KErrOverflow;
       
   279 			}
       
   280 		}
       
   281 	aCount = iLastPixelFormats.Count();
       
   282 	iMutex.Signal();
       
   283 	return err;
       
   284 	}
       
   285 
       
   286 
       
   287 TInt XSgDriverImpl::CreateImage(const TSgImageInfo& aInfo, const TAny* aDataAddress, TInt aDataStride, MSgDrawableAdapter*& aResult)
       
   288 	{
       
   289 	if (!SgIsValidImageInfo(aInfo))
       
   290 		{
       
   291 		return KErrArgument;
       
   292 		}
       
   293 	if (aResult)
       
   294 		{
       
   295 		return KErrInUse;
       
   296 		}
       
   297 	if (!aDataAddress && !SgIsMutableImage(aInfo))
       
   298 		{
       
   299 		return KErrNoInitializationData;
       
   300 		}
       
   301 	TInt err = CanCreateImage(aInfo);
       
   302 	if (err != KErrNone)
       
   303 		{
       
   304 		return err;
       
   305 		}
       
   306 #if !defined(SYMBIAN_GRAPHICS_USE_GPU) && !defined(__WINS__)
       
   307 	if (!aInfo.iShareable)
       
   308 		{
       
   309 		iMutex.Wait();
       
   310 		union
       
   311 			{
       
   312 			TSgDrawableId id;
       
   313 			TSgImageId_SwLocal id_SwLocal;
       
   314 			};
       
   315 		do
       
   316 			{
       
   317 			id_SwLocal.iProcessId = RProcess().Id();
       
   318 			id_SwLocal.iRandom[0] = Math::Random();
       
   319 			id_SwLocal.iRandom[1] = Math::Random();
       
   320 			id_SwLocal.iMinusOne = KErrNotFound;
       
   321 			id_SwLocal.iFlags = 0;
       
   322 			}
       
   323 		while (iImages.FindInOrder(id, XSgImageImplBase::Compare) != KErrNotFound);
       
   324 		XSgImageImpl_SwLocal* impl;
       
   325 		err = XSgImageImpl_SwLocal::New(impl, *this, id, aInfo, aDataAddress, aDataStride);
       
   326 		if (err != KErrNone)
       
   327 			{
       
   328 			iMutex.Signal();
       
   329 			return err;
       
   330 			}
       
   331 		RHeap* prevHeap = User::SwitchHeap(iHeap);
       
   332 		err = iImages.InsertInOrder(impl, XSgImageImplBase::Compare);
       
   333 		User::SwitchHeap(prevHeap);
       
   334 		if (err != KErrNone)
       
   335 			{
       
   336 			impl->Delete();
       
   337 			iMutex.Signal();
       
   338 			return err;
       
   339 			}
       
   340 		impl->IncRefCount();
       
   341 		aResult = impl;
       
   342 		iMutex.Signal();
       
   343 		return KErrNone;
       
   344 		}
       
   345 #endif
       
   346 	iMutex.Wait();
       
   347 	XSgImageImpl_SurfaceManager* impl;
       
   348 	err = XSgImageImpl_SurfaceManager::New(impl, *this, aInfo, SgIsCachedImage(aInfo), aDataAddress, aDataStride);
       
   349 	if (err != KErrNone)
       
   350 		{
       
   351 		iMutex.Signal();
       
   352 		return err;
       
   353 		}
       
   354 	RHeap* prevHeap = User::SwitchHeap(iHeap);
       
   355 	err = iImages.InsertInOrder(impl, XSgImageImplBase::Compare);
       
   356 	User::SwitchHeap(prevHeap);
       
   357 	if (err != KErrNone)
       
   358 		{
       
   359 		impl->Delete();
       
   360 		iMutex.Signal();
       
   361 		return err;
       
   362 		}
       
   363 	impl->IncRefCount();
       
   364 	aResult = impl;
       
   365 	iMutex.Signal();
       
   366 	return KErrNone;
       
   367 	}
       
   368 
       
   369 
       
   370 TInt XSgDriverImpl::CreateImage(const TSgImageInfo& aInfo, MSgImageAdapter* aImage, MSgDrawableAdapter*& aResult)
       
   371 	{
       
   372 	if (!aImage)
       
   373 		{
       
   374 		return KErrArgument;
       
   375 		}
       
   376 	__ASSERT_DEBUG(CheckImage(*aImage), Panic(ESgPanicBadImageHandle));
       
   377 	XSgImageImplBase& impl = static_cast<XSgImageImplBase&>(*aImage);
       
   378 	if (aInfo.iSizeInPixels != impl.MetaData().iSizeInPixels
       
   379 		|| aInfo.iPixelFormat != impl.MetaData().iPixelFormat)
       
   380 		{
       
   381 		return KErrNotSupported;
       
   382 		}
       
   383 	TInt err = impl.BeginDataAccess(ESgCpuAccessReadOnly);
       
   384 	if (err != KErrNone)
       
   385 		{
       
   386 		return err;
       
   387 		}
       
   388 	err = CreateImage(aInfo, impl.DataAddress(), impl.DataStride(), aResult);
       
   389 	impl.EndDataAccess();
       
   390 	return err;
       
   391 	}
       
   392 
       
   393 
       
   394 TInt XSgDriverImpl::CreateImageCollection(const TSgImageInfo& aInfo, TInt aImageCount, MSgImageCollectionAdapter*& aResult)
       
   395 	{
       
   396 	if (!SgIsValidImageInfo(aInfo) || aImageCount <= 0)
       
   397 		{
       
   398 		return KErrArgument;
       
   399 		}
       
   400 	if (aResult)
       
   401 		{
       
   402 		return KErrInUse;
       
   403 		}
       
   404 	if (!SgIsMutableImage(aInfo))
       
   405 		{
       
   406 		return KErrNotSupported;
       
   407 		}
       
   408 	TInt err = CanCreateImage(aInfo);
       
   409 	if (err != KErrNone)
       
   410 		{
       
   411 		return err;
       
   412 		}
       
   413 	iMutex.Wait();
       
   414 	XSgImageCollectionImpl* impl;
       
   415 	const TInt stride = SgAlignedDataStride(aInfo.iSizeInPixels.iWidth, aInfo.iPixelFormat);
       
   416 	const TInt offsetToFirst = SgOffsetToFirstBuffer(sizeof(TSgImageMetaData));
       
   417 	const TInt offsetBetween = SgOffsetBetweenBuffers(stride, aInfo.iSizeInPixels.iHeight);
       
   418 	
       
   419 	err = XSgImageCollectionImpl::New(impl, *this, aInfo, aImageCount, SgIsCachedImage(aInfo), stride, offsetToFirst, offsetBetween);
       
   420 	if (err != KErrNone)
       
   421 		{
       
   422 		iMutex.Signal();
       
   423 		return err;
       
   424 		}
       
   425 	RHeap* prevHeap = User::SwitchHeap(iHeap);
       
   426 	err = iImageCollections.InsertInAddressOrder(impl);
       
   427 	User::SwitchHeap(prevHeap);
       
   428 	if (err != KErrNone)
       
   429 		{
       
   430 		impl->Delete();
       
   431 		iMutex.Signal();
       
   432 		return err;
       
   433 		}
       
   434 	impl->IncRefCount();
       
   435 	aResult = impl;
       
   436 	iMutex.Signal();
       
   437 	return KErrNone;
       
   438 	}
       
   439 
       
   440 TInt XSgDriverImpl::GetBufferOffset(const TSurfaceId& aSurfaceID, TInt aBuffer, TInt &aOffset)
       
   441 	{
       
   442 	return iSurfaceManager.GetBufferOffset(aSurfaceID,aBuffer,aOffset);
       
   443 	}
       
   444 
       
   445 TInt XSgDriverImpl::GetSurfaceManagerAttrib(RSurfaceManager::TSurfaceManagerAttrib aAttrib, TInt& aValue)
       
   446 	{
       
   447 	return iSurfaceManager.GetSurfaceManagerAttrib(aAttrib,aValue);
       
   448 	}
       
   449 
       
   450 TInt XSgDriverImpl::CreateImageCollections(const TSgImageInfo aInfos[], TInt aImageCount,
       
   451                                            MSgImageCollectionAdapter* aCollections[], TInt aCollectionCount)
       
   452 	{
       
   453 	if (aImageCount <= 0 || aCollectionCount <= 0)
       
   454 		{
       
   455 		return KErrArgument;
       
   456 		}
       
   457 	TBool isCached = EFalse;
       
   458 	TInt offsetToFirstBuffer = SgOffsetToFirstBuffer(aCollectionCount * sizeof(TSgImageMetaData));
       
   459 	TInt maxOffsetBetweenBuffers = 0;
       
   460 	for (TInt i = 0; i < aCollectionCount; ++i)
       
   461 		{
       
   462 		const TSgImageInfo& info = aInfos[i];
       
   463 		if (!SgIsValidImageInfo(info))
       
   464 			{
       
   465 			return KErrArgument;
       
   466 			}
       
   467 		if (aCollections[i])
       
   468 			{
       
   469 			return KErrInUse;
       
   470 			}
       
   471 		if (!SgIsMutableImage(info))
       
   472 			{
       
   473 			return KErrNotSupported;
       
   474 			}
       
   475 		TInt err = CanCreateImage(info);
       
   476 		if (err != KErrNone)
       
   477 			{
       
   478 			return err;
       
   479 			}
       
   480 		if (SgIsCachedImage(info))
       
   481 			{
       
   482 			isCached = ETrue;
       
   483 			}
       
   484 		TInt stride = SgAlignedDataStride(info.iSizeInPixels.iWidth, info.iPixelFormat);
       
   485 		TInt offsetBetweenBuffers = SgOffsetBetweenBuffers(stride, info.iSizeInPixels.iHeight);
       
   486 		if (offsetBetweenBuffers > maxOffsetBetweenBuffers)
       
   487 			{
       
   488 			maxOffsetBetweenBuffers = offsetBetweenBuffers;
       
   489 			}
       
   490 		}
       
   491 	iMutex.Wait();
       
   492 	XSgImageCollectionImpl* firstImpl = NULL;
       
   493 	for (TInt i = 0; i < aCollectionCount; ++i)
       
   494 		{
       
   495 		const TInt stride = SgAlignedDataStride(aInfos[i].iSizeInPixels.iWidth, aInfos[i].iPixelFormat);
       
   496 		XSgImageCollectionImpl* impl;
       
   497 		TInt err = XSgImageCollectionImpl::New(impl, *this, aInfos[i], aImageCount, isCached,
       
   498 		                                       stride, offsetToFirstBuffer, maxOffsetBetweenBuffers, i, firstImpl);
       
   499 		if (err == KErrNone)
       
   500 			{
       
   501 			if (i == 0)
       
   502 				{
       
   503 				firstImpl = impl;
       
   504 				RSurfaceManager::TInfoBuf info;
       
   505 				TSurfaceId surface=impl->SurfaceId();
       
   506 				err = SurfaceInfo(surface, info);
       
   507 				if (err == KErrNone)
       
   508 				    {
       
   509 				    // get the actual value used for offset to first buffer
       
   510 				    err = iSurfaceManager.GetBufferOffset(surface, 0, offsetToFirstBuffer);
       
   511 				    // get the actual value used for offset between buffers
       
   512 				    if (aImageCount>1)
       
   513 				    	{
       
   514 				    	TInt offsetToSecondBuffer;
       
   515 				    	err = iSurfaceManager.GetBufferOffset(surface, 1, offsetToSecondBuffer);
       
   516 				    	maxOffsetBetweenBuffers = offsetToSecondBuffer - offsetToFirstBuffer;
       
   517 				    	}
       
   518 				    else
       
   519 				    	{
       
   520 				    	maxOffsetBetweenBuffers = 0;
       
   521 				    	}
       
   522 				    }       
       
   523 				if (err != KErrNone)
       
   524 				    {
       
   525 				    impl->Delete();
       
   526 				    iMutex.Signal();
       
   527 				    return err;
       
   528 				    } 					
       
   529 				}
       
   530 			RHeap* prevHeap = User::SwitchHeap(iHeap);
       
   531 			err = iImageCollections.InsertInAddressOrder(impl);
       
   532 			User::SwitchHeap(prevHeap);
       
   533 			if (err == KErrNone)
       
   534 				{
       
   535 				impl->IncRefCount();
       
   536 				aCollections[i] = impl;
       
   537 				}
       
   538 			else
       
   539 				{
       
   540 				impl->Delete();
       
   541 				}
       
   542 			}
       
   543 		if (err != KErrNone)
       
   544 			{
       
   545 			while (--i >= 0)
       
   546 				{
       
   547 				aCollections[i]->Close();
       
   548 				aCollections[i] = NULL;
       
   549 				}
       
   550 			iMutex.Signal();
       
   551 			return err;
       
   552 			}
       
   553 		}
       
   554 	iMutex.Signal();
       
   555 	return KErrNone;
       
   556 	}
       
   557 
       
   558 
       
   559 TInt XSgDriverImpl::OpenDrawable(const TSgDrawableId& aId, TUint32 aMode, TUid aHandleType, MSgDrawableAdapter*& aResult)
       
   560 	{
       
   561 	if (aHandleType == KSgImageTypeUid || aHandleType == KSgDrawableTypeUid)
       
   562 		{
       
   563 		return OpenImage(aId, aMode, aResult);
       
   564 		}
       
   565 	return KErrNotSupported;
       
   566 	}
       
   567 
       
   568 
       
   569 TInt XSgDriverImpl::OpenImage(const TSgDrawableId& aId, TUint32 aMode, MSgDrawableAdapter*& aResult)
       
   570 	{
       
   571 	if (aResult)
       
   572 		{
       
   573 		return KErrInUse;
       
   574 		}
       
   575 	iMutex.Wait();
       
   576 	TSgDrawableId id = aId;
       
   577 	id.iId[KSgImageIdFlagsIndex] |= aMode;
       
   578 	TInt i = iImages.FindInOrder(id, XSgImageImplBase::CompareIgnoringFlags);
       
   579 	if (i != KErrNotFound)
       
   580 		{
       
   581 		XSgImageImplBase* impl;
       
   582 		TInt j = iImages.FindInOrder(id, XSgImageImplBase::Compare);
       
   583 		if (j != KErrNotFound)
       
   584 			{
       
   585 			impl = iImages[j];
       
   586 			}
       
   587 		else
       
   588 			{
       
   589 			impl = iImages[i];
       
   590 #ifndef SYMBIAN_GRAPHICS_USE_GPU
       
   591 			if (TSgImageId_SwLocal::IsMatch(id))
       
   592 				{
       
   593 				XSgImageImpl_SwLocal* impl2;
       
   594 				TInt err = XSgImageImpl_SwLocal::New(impl2, *static_cast<XSgImageImpl_SwLocal*>(impl), id.iId[KSgImageIdFlagsIndex]);
       
   595 				if (err != KErrNone)
       
   596 					{
       
   597 					iMutex.Signal();
       
   598 					return err;
       
   599 					}
       
   600 				impl = impl2;
       
   601 				}
       
   602 			else
       
   603 #endif
       
   604 			if (TSgImageId_SurfaceManager::IsMatch(id))
       
   605 				{
       
   606 				XSgImageImpl_SurfaceManager* impl2;
       
   607 				TInt err = XSgImageImpl_SurfaceManager::New(impl2, *static_cast<XSgImageImpl_SurfaceManager*>(impl), id.iId[KSgImageIdFlagsIndex]);
       
   608 				if (err != KErrNone)
       
   609 					{
       
   610 					iMutex.Signal();
       
   611 					return err;
       
   612 					}
       
   613 				impl = impl2;
       
   614 				}
       
   615 			else
       
   616 				{
       
   617 				iMutex.Signal();
       
   618 				return KErrNotFound;
       
   619 				}
       
   620 			RHeap* prevHeap = User::SwitchHeap(iHeap);
       
   621 			TInt err = iImages.InsertInOrder(impl, XSgImageImplBase::Compare);
       
   622 			User::SwitchHeap(prevHeap);
       
   623 			if (err != KErrNone)
       
   624 				{
       
   625 				impl->Delete();
       
   626 				iMutex.Signal();
       
   627 				return err;
       
   628 				}
       
   629 			}
       
   630 		impl->IncRefCount();
       
   631 		aResult = impl;
       
   632 		iMutex.Signal();
       
   633 		return KErrNone;
       
   634 		}
       
   635 	TInt err = KErrNotFound;
       
   636 	if (TSgImageId_SurfaceManager::IsMatch(id))
       
   637 		{
       
   638 		XSgImageImpl_SurfaceManager* impl;
       
   639 		err = XSgImageImpl_SurfaceManager::New(impl, *this, id);
       
   640 		if (err != KErrNone)
       
   641 			{
       
   642 			iMutex.Signal();
       
   643 			return err;
       
   644 			}
       
   645 		if (!impl->MetaData().iShareable && impl->MetaData().iCreatorProcess != RProcess().Id())
       
   646 			{
       
   647 			impl->Delete();
       
   648 			iMutex.Signal();
       
   649 			return KErrPermissionDenied;
       
   650 			}
       
   651 		RHeap* prevHeap = User::SwitchHeap(iHeap);
       
   652 		err = iImages.InsertInOrder(impl, XSgImageImplBase::Compare);
       
   653 		User::SwitchHeap(prevHeap);
       
   654 		if (err != KErrNone)
       
   655 			{
       
   656 			impl->Delete();
       
   657 			iMutex.Signal();
       
   658 			return err;
       
   659 			}
       
   660 		impl->IncRefCount();
       
   661 		aResult = impl;
       
   662 		}
       
   663 	iMutex.Signal();
       
   664 	return err;
       
   665 	}
       
   666 
       
   667 
       
   668 void XSgDriverImpl::DeleteImage(XSgImageImplBase* aImage)
       
   669 	{
       
   670 	__ASSERT_DEBUG(iMutex.IsHeld(), Panic(ESgPanicMutexNotHeld));
       
   671 	TInt i = iImages.FindInOrder(aImage, XSgImageImplBase::Compare);
       
   672 	__ASSERT_DEBUG(i != KErrNotFound, Panic(ESgPanicBadImageHandle));
       
   673 	RHeap* prevHeap = User::SwitchHeap(iHeap);
       
   674 	iImages.Remove(i);
       
   675 	iImages.GranularCompress();
       
   676 	User::SwitchHeap(prevHeap);
       
   677 	aImage->Delete();
       
   678 	}
       
   679 
       
   680 
       
   681 void XSgDriverImpl::DeleteImageCollection(XSgImageCollectionImpl* aImageCollection)
       
   682 	{
       
   683 	__ASSERT_DEBUG(iMutex.IsHeld(), Panic(ESgPanicMutexNotHeld));
       
   684 	TInt i = iImageCollections.FindInAddressOrder(aImageCollection);
       
   685 	__ASSERT_DEBUG(i != KErrNotFound, Panic(ESgPanicBadImageCollectionHandle));
       
   686 	RHeap* prevHeap = User::SwitchHeap(iHeap);
       
   687 	iImageCollections.Remove(i);
       
   688 	iImageCollections.GranularCompress();
       
   689 	User::SwitchHeap(prevHeap);
       
   690 	aImageCollection->Delete();
       
   691 	}
       
   692 
       
   693 
       
   694 TBool XSgDriverImpl::CheckDrawable(const MSgResourceAdapter& aDrawable) const
       
   695 	{
       
   696 	iMutex.Wait();
       
   697 	TInt i = iImages.Find(&static_cast<const XSgImageImplBase&>(aDrawable));
       
   698 	iMutex.Signal();
       
   699 	return i != KErrNotFound;
       
   700 	}
       
   701 
       
   702 
       
   703 TBool XSgDriverImpl::CheckImage(const MSgResourceAdapter& aImage) const
       
   704 	{
       
   705 	iMutex.Wait();
       
   706 	TInt i = iImages.Find(&static_cast<const XSgImageImplBase&>(aImage));
       
   707 	iMutex.Signal();
       
   708 	return i != KErrNotFound;
       
   709 	}
       
   710 
       
   711 
       
   712 TBool XSgDriverImpl::CheckImageCollection(const MSgResourceAdapter& aImageCollection) const
       
   713 	{
       
   714 	iMutex.Wait();
       
   715 	TInt i = iImageCollections.Find(&static_cast<const XSgImageCollectionImpl&>(aImageCollection));
       
   716 	iMutex.Signal();
       
   717 	return i != KErrNotFound;
       
   718 	}
       
   719 
       
   720 
       
   721 TInt XSgDriverImpl::ResourceCount() const
       
   722 	{
       
   723 	iMutex.Wait();
       
   724 	TInt count = 0;
       
   725 	for (TInt i = 0; i < iImages.Count(); ++i)
       
   726 		{
       
   727 		count += iImages[i]->RefCount();
       
   728 		}
       
   729 	for (TInt i = 0; i < iImageCollections.Count(); ++i)
       
   730 		{
       
   731 		count += iImageCollections[i]->RefCount();
       
   732 		}
       
   733 	iMutex.Signal();
       
   734 	return count;
       
   735 	}
       
   736 
       
   737 
       
   738 #ifdef _DEBUG
       
   739 
       
   740 void XSgDriverImpl::AllocMarkStart()
       
   741 	{
       
   742 	iMutex.Wait();
       
   743 	iHeap->__DbgMarkStart();
       
   744 	iMutex.Signal();
       
   745 	}
       
   746 
       
   747 
       
   748 void XSgDriverImpl::AllocMarkEnd(TInt aCount)
       
   749 	{
       
   750 	iMutex.Wait();
       
   751 	TUint32 badCell = iHeap->__DbgMarkEnd(aCount);
       
   752 	iMutex.Signal();
       
   753 	if (badCell != 0)
       
   754 		{
       
   755 		_LIT(KPanicCategoryFormat, "SGALLOC:%08x");
       
   756 		TBuf<0x10> category;
       
   757 		category.Format(KPanicCategoryFormat, badCell);
       
   758 		User::Panic(category, 0);
       
   759 		}
       
   760 	}
       
   761 
       
   762 
       
   763 void XSgDriverImpl::SetAllocFail(RAllocator::TAllocFail aType, TInt aRate)
       
   764 	{
       
   765 	iMutex.Wait();
       
   766 	iHeap->__DbgSetAllocFail(aType, aRate);
       
   767 	iMutex.Signal();
       
   768 	}
       
   769 
       
   770 #else
       
   771 
       
   772 void XSgDriverImpl::AllocMarkStart()
       
   773 	{
       
   774 	}
       
   775 
       
   776 
       
   777 void XSgDriverImpl::AllocMarkEnd(TInt /*aCount*/)
       
   778 	{
       
   779 	}
       
   780 
       
   781 
       
   782 void XSgDriverImpl::SetAllocFail(RAllocator::TAllocFail /*aType*/, TInt /*aRate*/)
       
   783 	{
       
   784 	}
       
   785 
       
   786 #endif
       
   787 
       
   788 
       
   789 // MSgDriverAdapter::New()
       
   790 
       
   791 EXPORT_C TInt MSgDriverAdapter::New(MSgDriverAdapter*& aPtr)
       
   792 	{
       
   793 	RHeap* heap = UserHeap::ChunkHeap(NULL, 0, KSgMaxLocalChunkSize);
       
   794 	if (!heap)
       
   795 		{
       
   796 		return KErrNoMemory;
       
   797 		}
       
   798 	XSgDriverImpl* driverImpl = static_cast<XSgDriverImpl*>(heap->Alloc(sizeof(XSgDriverImpl)));
       
   799 	if (!driverImpl)
       
   800 		{
       
   801 		heap->Close();
       
   802 		return KErrNoMemory;
       
   803 		}
       
   804 	new(driverImpl) XSgDriverImpl(heap);
       
   805 	TInt err = driverImpl->Construct();
       
   806 	if (err != KErrNone)
       
   807 		{
       
   808 		driverImpl->Delete();
       
   809 		return err;
       
   810 		}
       
   811 	aPtr = driverImpl;
       
   812 	return KErrNone;
       
   813 	}