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