sl@0: // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include sl@0: #include "sgdriverimpl.h" sl@0: #include "sgimageimpl.h" sl@0: #include "sgimagecollectionimpl.h" sl@0: sl@0: sl@0: TInt SgAlignedDataStride(TInt aWidthInPixels, TUidPixelFormat aPixelFormat) sl@0: { sl@0: #if defined(SYMBIAN_GRAPHICS_USE_MBX) sl@0: // MBX requires 2^n stride. sl@0: for (TInt width = 8; width & KMaxTInt; width <<= 1) sl@0: { sl@0: if (width >= aWidthInPixels) sl@0: { sl@0: aWidthInPixels = width; sl@0: break; sl@0: } sl@0: } sl@0: #elif defined(SYMBIAN_GRAPHICS_USE_SGX) sl@0: // SGX requires a 32 pixel alignment. sl@0: aWidthInPixels = (aWidthInPixels + 31) & ~31; sl@0: #endif sl@0: return Align4(SgMinDataStride(aWidthInPixels, aPixelFormat)); sl@0: } sl@0: sl@0: sl@0: TInt SgOffsetToFirstBuffer(TInt aMetaDataSize) sl@0: { sl@0: #if defined(SYMBIAN_GRAPHICS_USE_MBX) || defined(SYMBIAN_GRAPHICS_USE_SGX) sl@0: return (aMetaDataSize + 127) & ~127; sl@0: #else sl@0: return Align4(aMetaDataSize); sl@0: #endif sl@0: } sl@0: sl@0: sl@0: TInt SgOffsetBetweenBuffers(TInt aDataStride, TInt aScanLineCount) sl@0: { sl@0: #if defined(SYMBIAN_GRAPHICS_USE_MBX) sl@0: for (TInt count = 16; count & KMaxTInt; count <<= 1) sl@0: { sl@0: if (count >= aScanLineCount) sl@0: { sl@0: aScanLineCount = count; sl@0: break; sl@0: } sl@0: } sl@0: #endif sl@0: return aDataStride * aScanLineCount; sl@0: } sl@0: sl@0: sl@0: TBool SgIsValidImageInfo(const TSgImageInfo& aInfo) sl@0: { sl@0: return aInfo.iSizeInPixels.iWidth > 0 && aInfo.iSizeInPixels.iHeight > 0 sl@0: && (aInfo.iUsage & ESgUsageScreenSource ? aInfo.iScreenId >= KSgScreenIdMain : aInfo.iScreenId >= KSgScreenIdAny) sl@0: && (aInfo.iUserAttributes ? aInfo.iUserAttributeCount > 0 : aInfo.iUserAttributeCount == 0); sl@0: } sl@0: sl@0: sl@0: TBool SgIsMutableImage(const TSgImageInfo& aInfo) sl@0: { sl@0: return (aInfo.iCpuAccess & ESgCpuAccessWritable) || (aInfo.iUsage & KSgUsageAllTargets); sl@0: } sl@0: sl@0: sl@0: TBool SgIsCachedImage(const TSgImageInfo& aInfo) sl@0: { sl@0: #ifdef SYMBIAN_GRAPHICS_USE_GPU sl@0: #ifdef SYMBIAN_GRAPHICS_USE_CACHE sl@0: return aInfo.iCpuAccess != ESgCpuAccessNone; sl@0: #else sl@0: (void)aInfo; sl@0: return EFalse; sl@0: #endif sl@0: #else sl@0: (void)aInfo; sl@0: return ETrue; sl@0: #endif sl@0: } sl@0: sl@0: sl@0: // TSgPixelFormatTableEntry sl@0: sl@0: TBool TSgPixelFormatTableEntry::IsMatch(const TSgImageInfo& aInfo) const sl@0: { sl@0: return iPixelFormat == aInfo.iPixelFormat sl@0: && !(~iUsage & aInfo.iUsage) sl@0: && !(~iCpuAccess & aInfo.iCpuAccess) sl@0: && (iScreenId == KSgScreenIdAny || iScreenId == aInfo.iScreenId); sl@0: } sl@0: sl@0: sl@0: TBool TSgPixelFormatTableEntry::IsMatchIgnoringPixelFormat(const TSgImageInfo& aInfo) const sl@0: { sl@0: return !(~iUsage & aInfo.iUsage) sl@0: && !(~iCpuAccess & aInfo.iCpuAccess) sl@0: && (iScreenId == KSgScreenIdAny || iScreenId == aInfo.iScreenId); sl@0: } sl@0: sl@0: sl@0: TBool TSgPixelFormatTableEntry::IsMatchIgnoringUsage(const TSgImageInfo& aInfo) const sl@0: { sl@0: return iPixelFormat == aInfo.iPixelFormat sl@0: && !(~iCpuAccess & aInfo.iCpuAccess) sl@0: && (iScreenId == KSgScreenIdAny || iScreenId == aInfo.iScreenId); sl@0: } sl@0: sl@0: sl@0: // XSgBase sl@0: sl@0: XSgBase::~XSgBase() sl@0: { sl@0: __ASSERT_DEBUG(iDriverImpl.IsMutexHeld(), Panic(ESgPanicMutexNotHeld)); sl@0: __ASSERT_DEBUG(iRefCount == 0, Panic(ESgPanicBadReferenceCount)); sl@0: } sl@0: sl@0: sl@0: void XSgBase::Delete() sl@0: { sl@0: XSgDriverImpl& driverImpl = iDriverImpl; sl@0: this->~XSgBase(); sl@0: driverImpl.Free(this); sl@0: } sl@0: sl@0: sl@0: // XSgDriverImpl sl@0: sl@0: TInt XSgDriverImpl::Construct() sl@0: { sl@0: TInt err = iMutex.CreateLocal(); sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: err = iSurfaceManager.Open(); sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: return ConstructPixelFormatTable(); sl@0: } sl@0: sl@0: sl@0: XSgDriverImpl::~XSgDriverImpl() sl@0: { sl@0: __ASSERT_DEBUG(iImages.Count() == 0, Panic(ESgPanicUnclosedResources)); sl@0: __ASSERT_DEBUG(iImageCollections.Count() == 0, Panic(ESgPanicUnclosedResources)); sl@0: iMutex.Close(); sl@0: iSurfaceManager.Close(); sl@0: RHeap* prevHeap = User::SwitchHeap(iHeap); sl@0: iPixelFormatTable.Close(); sl@0: iLastPixelFormats.Close(); sl@0: User::SwitchHeap(prevHeap); sl@0: } sl@0: sl@0: sl@0: void XSgDriverImpl::Delete() sl@0: { sl@0: RHeap* heap = iHeap; sl@0: this->~XSgDriverImpl(); sl@0: heap->Free(this); sl@0: __ASSERT_DEBUG(heap->Count() == 0, Panic(ESgPanicUnclosedResources)); sl@0: heap->Close(); sl@0: } sl@0: sl@0: sl@0: TInt XSgDriverImpl::MapSurface(const TSurfaceId& aSurfaceId, RChunk& aChunk) sl@0: { sl@0: RChunk chunk; sl@0: TInt err = iSurfaceManager.MapSurface(aSurfaceId, chunk); sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: aChunk = chunk; sl@0: err = aChunk.Duplicate(RThread()); // Get a process-wide handle sl@0: chunk.Close(); sl@0: return err; sl@0: } sl@0: sl@0: sl@0: TArray XSgDriverImpl::PixelFormatTable() const sl@0: { sl@0: return iPixelFormatTable.Array(); sl@0: } sl@0: sl@0: sl@0: TInt XSgDriverImpl::CanCreateImage(const TSgImageInfo& aInfo) const sl@0: { sl@0: __ASSERT_DEBUG(SgIsValidImageInfo(aInfo), Panic(ESgPanicBadImageInfo)); sl@0: if (aInfo.iSizeInPixels.iWidth > KMaxTInt16 / 2 || aInfo.iSizeInPixels.iHeight > KMaxTInt16 / 2) sl@0: { sl@0: return KErrTooBig; sl@0: } sl@0: TArray pixelFormatTable = PixelFormatTable(); sl@0: TInt n = pixelFormatTable.Count(); sl@0: for (TInt i = 0; i < n; ++i) sl@0: { sl@0: if (pixelFormatTable[i].IsMatch(aInfo)) sl@0: { sl@0: return SgMinDataStride(aInfo.iSizeInPixels.iWidth, aInfo.iPixelFormat) > 0 ? KErrNone : KErrNotSupported; sl@0: } sl@0: } sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: sl@0: TInt XSgDriverImpl::GetPixelFormats(const TSgImageInfo& aInfo, TUidPixelFormat* aPixelFormats, TInt& aCount) sl@0: { sl@0: if (!SgIsValidImageInfo(aInfo) || (aPixelFormats && aCount < 0)) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: iMutex.Wait(); sl@0: if (aInfo.iSizeInPixels != iLastSizeInPixels sl@0: || aInfo.iUsage != iLastUsage sl@0: || aInfo.iCpuAccess != iLastCpuAccess sl@0: || aInfo.iScreenId != iLastScreenId) sl@0: { sl@0: iLastSizeInPixels = aInfo.iSizeInPixels; sl@0: iLastUsage = aInfo.iUsage; sl@0: iLastCpuAccess = aInfo.iCpuAccess; sl@0: iLastScreenId = aInfo.iScreenId; sl@0: RHeap* prevHeap = User::SwitchHeap(iHeap); sl@0: iLastPixelFormats.Reset(); sl@0: User::SwitchHeap(prevHeap); sl@0: TArray pixelFormatTable = PixelFormatTable(); sl@0: TInt n = pixelFormatTable.Count(); sl@0: for (TInt i = 0; i < n; ++i) sl@0: { sl@0: const TSgPixelFormatTableEntry& entry = pixelFormatTable[i]; sl@0: if (entry.IsMatchIgnoringPixelFormat(aInfo) && iLastPixelFormats.Find(entry.iPixelFormat) == KErrNotFound) sl@0: { sl@0: User::SwitchHeap(iHeap); sl@0: TInt err = iLastPixelFormats.Append(entry.iPixelFormat); sl@0: User::SwitchHeap(prevHeap); sl@0: if (err != KErrNone) sl@0: { sl@0: iLastSizeInPixels = TSize(0, 0); sl@0: iLastUsage = ESgUsageNone; sl@0: iLastCpuAccess = ESgCpuAccessNone; sl@0: iLastScreenId = KSgScreenIdMain; sl@0: User::SwitchHeap(iHeap); sl@0: iLastPixelFormats.Reset(); sl@0: User::SwitchHeap(prevHeap); sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: TInt err = KErrNone; sl@0: if (aPixelFormats) sl@0: { sl@0: TInt n = Min(aCount, iLastPixelFormats.Count()); sl@0: for (TInt i = 0; i < n; ++i) sl@0: { sl@0: aPixelFormats[i] = iLastPixelFormats[i]; sl@0: } sl@0: if (aCount < iLastPixelFormats.Count()) sl@0: { sl@0: err = KErrOverflow; sl@0: } sl@0: } sl@0: aCount = iLastPixelFormats.Count(); sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: sl@0: sl@0: TInt XSgDriverImpl::CreateImage(const TSgImageInfo& aInfo, const TAny* aDataAddress, TInt aDataStride, MSgDrawableAdapter*& aResult) sl@0: { sl@0: if (!SgIsValidImageInfo(aInfo)) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: if (aResult) sl@0: { sl@0: return KErrInUse; sl@0: } sl@0: if (!aDataAddress && !SgIsMutableImage(aInfo)) sl@0: { sl@0: return KErrNoInitializationData; sl@0: } sl@0: TInt err = CanCreateImage(aInfo); sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: #if !defined(SYMBIAN_GRAPHICS_USE_GPU) && !defined(__WINS__) sl@0: if (!aInfo.iShareable) sl@0: { sl@0: iMutex.Wait(); sl@0: union sl@0: { sl@0: TSgDrawableId id; sl@0: TSgImageId_SwLocal id_SwLocal; sl@0: }; sl@0: do sl@0: { sl@0: id_SwLocal.iProcessId = RProcess().Id(); sl@0: id_SwLocal.iRandom[0] = Math::Random(); sl@0: id_SwLocal.iRandom[1] = Math::Random(); sl@0: id_SwLocal.iMinusOne = KErrNotFound; sl@0: id_SwLocal.iFlags = 0; sl@0: } sl@0: while (iImages.FindInOrder(id, XSgImageImplBase::Compare) != KErrNotFound); sl@0: XSgImageImpl_SwLocal* impl; sl@0: err = XSgImageImpl_SwLocal::New(impl, *this, id, aInfo, aDataAddress, aDataStride); sl@0: if (err != KErrNone) sl@0: { sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: RHeap* prevHeap = User::SwitchHeap(iHeap); sl@0: err = iImages.InsertInOrder(impl, XSgImageImplBase::Compare); sl@0: User::SwitchHeap(prevHeap); sl@0: if (err != KErrNone) sl@0: { sl@0: impl->Delete(); sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: impl->IncRefCount(); sl@0: aResult = impl; sl@0: iMutex.Signal(); sl@0: return KErrNone; sl@0: } sl@0: #endif sl@0: iMutex.Wait(); sl@0: XSgImageImpl_SurfaceManager* impl; sl@0: err = XSgImageImpl_SurfaceManager::New(impl, *this, aInfo, SgIsCachedImage(aInfo), aDataAddress, aDataStride); sl@0: if (err != KErrNone) sl@0: { sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: RHeap* prevHeap = User::SwitchHeap(iHeap); sl@0: err = iImages.InsertInOrder(impl, XSgImageImplBase::Compare); sl@0: User::SwitchHeap(prevHeap); sl@0: if (err != KErrNone) sl@0: { sl@0: impl->Delete(); sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: impl->IncRefCount(); sl@0: aResult = impl; sl@0: iMutex.Signal(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt XSgDriverImpl::CreateImage(const TSgImageInfo& aInfo, MSgImageAdapter* aImage, MSgDrawableAdapter*& aResult) sl@0: { sl@0: if (!aImage) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: __ASSERT_DEBUG(CheckImage(*aImage), Panic(ESgPanicBadImageHandle)); sl@0: XSgImageImplBase& impl = static_cast(*aImage); sl@0: if (aInfo.iSizeInPixels != impl.MetaData().iSizeInPixels sl@0: || aInfo.iPixelFormat != impl.MetaData().iPixelFormat) sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: TInt err = impl.BeginDataAccess(ESgCpuAccessReadOnly); sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: err = CreateImage(aInfo, impl.DataAddress(), impl.DataStride(), aResult); sl@0: impl.EndDataAccess(); sl@0: return err; sl@0: } sl@0: sl@0: sl@0: TInt XSgDriverImpl::CreateImageCollection(const TSgImageInfo& aInfo, TInt aImageCount, MSgImageCollectionAdapter*& aResult) sl@0: { sl@0: if (!SgIsValidImageInfo(aInfo) || aImageCount <= 0) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: if (aResult) sl@0: { sl@0: return KErrInUse; sl@0: } sl@0: if (!SgIsMutableImage(aInfo)) sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: TInt err = CanCreateImage(aInfo); sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: iMutex.Wait(); sl@0: XSgImageCollectionImpl* impl; sl@0: const TInt stride = SgAlignedDataStride(aInfo.iSizeInPixels.iWidth, aInfo.iPixelFormat); sl@0: const TInt offsetToFirst = SgOffsetToFirstBuffer(sizeof(TSgImageMetaData)); sl@0: const TInt offsetBetween = SgOffsetBetweenBuffers(stride, aInfo.iSizeInPixels.iHeight); sl@0: sl@0: err = XSgImageCollectionImpl::New(impl, *this, aInfo, aImageCount, SgIsCachedImage(aInfo), stride, offsetToFirst, offsetBetween); sl@0: if (err != KErrNone) sl@0: { sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: RHeap* prevHeap = User::SwitchHeap(iHeap); sl@0: err = iImageCollections.InsertInAddressOrder(impl); sl@0: User::SwitchHeap(prevHeap); sl@0: if (err != KErrNone) sl@0: { sl@0: impl->Delete(); sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: impl->IncRefCount(); sl@0: aResult = impl; sl@0: iMutex.Signal(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt XSgDriverImpl::GetBufferOffset(const TSurfaceId& aSurfaceID, TInt aBuffer, TInt &aOffset) sl@0: { sl@0: return iSurfaceManager.GetBufferOffset(aSurfaceID,aBuffer,aOffset); sl@0: } sl@0: sl@0: TInt XSgDriverImpl::GetSurfaceManagerAttrib(RSurfaceManager::TSurfaceManagerAttrib aAttrib, TInt& aValue) sl@0: { sl@0: return iSurfaceManager.GetSurfaceManagerAttrib(aAttrib,aValue); sl@0: } sl@0: sl@0: TInt XSgDriverImpl::CreateImageCollections(const TSgImageInfo aInfos[], TInt aImageCount, sl@0: MSgImageCollectionAdapter* aCollections[], TInt aCollectionCount) sl@0: { sl@0: if (aImageCount <= 0 || aCollectionCount <= 0) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: TBool isCached = EFalse; sl@0: TInt offsetToFirstBuffer = SgOffsetToFirstBuffer(aCollectionCount * sizeof(TSgImageMetaData)); sl@0: TInt maxOffsetBetweenBuffers = 0; sl@0: for (TInt i = 0; i < aCollectionCount; ++i) sl@0: { sl@0: const TSgImageInfo& info = aInfos[i]; sl@0: if (!SgIsValidImageInfo(info)) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: if (aCollections[i]) sl@0: { sl@0: return KErrInUse; sl@0: } sl@0: if (!SgIsMutableImage(info)) sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: TInt err = CanCreateImage(info); sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: if (SgIsCachedImage(info)) sl@0: { sl@0: isCached = ETrue; sl@0: } sl@0: TInt stride = SgAlignedDataStride(info.iSizeInPixels.iWidth, info.iPixelFormat); sl@0: TInt offsetBetweenBuffers = SgOffsetBetweenBuffers(stride, info.iSizeInPixels.iHeight); sl@0: if (offsetBetweenBuffers > maxOffsetBetweenBuffers) sl@0: { sl@0: maxOffsetBetweenBuffers = offsetBetweenBuffers; sl@0: } sl@0: } sl@0: iMutex.Wait(); sl@0: XSgImageCollectionImpl* firstImpl = NULL; sl@0: for (TInt i = 0; i < aCollectionCount; ++i) sl@0: { sl@0: const TInt stride = SgAlignedDataStride(aInfos[i].iSizeInPixels.iWidth, aInfos[i].iPixelFormat); sl@0: XSgImageCollectionImpl* impl; sl@0: TInt err = XSgImageCollectionImpl::New(impl, *this, aInfos[i], aImageCount, isCached, sl@0: stride, offsetToFirstBuffer, maxOffsetBetweenBuffers, i, firstImpl); sl@0: if (err == KErrNone) sl@0: { sl@0: if (i == 0) sl@0: { sl@0: firstImpl = impl; sl@0: RSurfaceManager::TInfoBuf info; sl@0: TSurfaceId surface=impl->SurfaceId(); sl@0: err = SurfaceInfo(surface, info); sl@0: if (err == KErrNone) sl@0: { sl@0: // get the actual value used for offset to first buffer sl@0: err = iSurfaceManager.GetBufferOffset(surface, 0, offsetToFirstBuffer); sl@0: // get the actual value used for offset between buffers sl@0: if (aImageCount>1) sl@0: { sl@0: TInt offsetToSecondBuffer; sl@0: err = iSurfaceManager.GetBufferOffset(surface, 1, offsetToSecondBuffer); sl@0: maxOffsetBetweenBuffers = offsetToSecondBuffer - offsetToFirstBuffer; sl@0: } sl@0: else sl@0: { sl@0: maxOffsetBetweenBuffers = 0; sl@0: } sl@0: } sl@0: if (err != KErrNone) sl@0: { sl@0: impl->Delete(); sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: } sl@0: RHeap* prevHeap = User::SwitchHeap(iHeap); sl@0: err = iImageCollections.InsertInAddressOrder(impl); sl@0: User::SwitchHeap(prevHeap); sl@0: if (err == KErrNone) sl@0: { sl@0: impl->IncRefCount(); sl@0: aCollections[i] = impl; sl@0: } sl@0: else sl@0: { sl@0: impl->Delete(); sl@0: } sl@0: } sl@0: if (err != KErrNone) sl@0: { sl@0: while (--i >= 0) sl@0: { sl@0: aCollections[i]->Close(); sl@0: aCollections[i] = NULL; sl@0: } sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: } sl@0: iMutex.Signal(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt XSgDriverImpl::OpenDrawable(const TSgDrawableId& aId, TUint32 aMode, TUid aHandleType, MSgDrawableAdapter*& aResult) sl@0: { sl@0: if (aHandleType == KSgImageTypeUid || aHandleType == KSgDrawableTypeUid) sl@0: { sl@0: return OpenImage(aId, aMode, aResult); sl@0: } sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: sl@0: TInt XSgDriverImpl::OpenImage(const TSgDrawableId& aId, TUint32 aMode, MSgDrawableAdapter*& aResult) sl@0: { sl@0: if (aResult) sl@0: { sl@0: return KErrInUse; sl@0: } sl@0: iMutex.Wait(); sl@0: TSgDrawableId id = aId; sl@0: id.iId[KSgImageIdFlagsIndex] |= aMode; sl@0: TInt i = iImages.FindInOrder(id, XSgImageImplBase::CompareIgnoringFlags); sl@0: if (i != KErrNotFound) sl@0: { sl@0: XSgImageImplBase* impl; sl@0: TInt j = iImages.FindInOrder(id, XSgImageImplBase::Compare); sl@0: if (j != KErrNotFound) sl@0: { sl@0: impl = iImages[j]; sl@0: } sl@0: else sl@0: { sl@0: impl = iImages[i]; sl@0: #ifndef SYMBIAN_GRAPHICS_USE_GPU sl@0: if (TSgImageId_SwLocal::IsMatch(id)) sl@0: { sl@0: XSgImageImpl_SwLocal* impl2; sl@0: TInt err = XSgImageImpl_SwLocal::New(impl2, *static_cast(impl), id.iId[KSgImageIdFlagsIndex]); sl@0: if (err != KErrNone) sl@0: { sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: impl = impl2; sl@0: } sl@0: else sl@0: #endif sl@0: if (TSgImageId_SurfaceManager::IsMatch(id)) sl@0: { sl@0: XSgImageImpl_SurfaceManager* impl2; sl@0: TInt err = XSgImageImpl_SurfaceManager::New(impl2, *static_cast(impl), id.iId[KSgImageIdFlagsIndex]); sl@0: if (err != KErrNone) sl@0: { sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: impl = impl2; sl@0: } sl@0: else sl@0: { sl@0: iMutex.Signal(); sl@0: return KErrNotFound; sl@0: } sl@0: RHeap* prevHeap = User::SwitchHeap(iHeap); sl@0: TInt err = iImages.InsertInOrder(impl, XSgImageImplBase::Compare); sl@0: User::SwitchHeap(prevHeap); sl@0: if (err != KErrNone) sl@0: { sl@0: impl->Delete(); sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: } sl@0: impl->IncRefCount(); sl@0: aResult = impl; sl@0: iMutex.Signal(); sl@0: return KErrNone; sl@0: } sl@0: TInt err = KErrNotFound; sl@0: if (TSgImageId_SurfaceManager::IsMatch(id)) sl@0: { sl@0: XSgImageImpl_SurfaceManager* impl; sl@0: err = XSgImageImpl_SurfaceManager::New(impl, *this, id); sl@0: if (err != KErrNone) sl@0: { sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: if (!impl->MetaData().iShareable && impl->MetaData().iCreatorProcess != RProcess().Id()) sl@0: { sl@0: impl->Delete(); sl@0: iMutex.Signal(); sl@0: return KErrPermissionDenied; sl@0: } sl@0: RHeap* prevHeap = User::SwitchHeap(iHeap); sl@0: err = iImages.InsertInOrder(impl, XSgImageImplBase::Compare); sl@0: User::SwitchHeap(prevHeap); sl@0: if (err != KErrNone) sl@0: { sl@0: impl->Delete(); sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: impl->IncRefCount(); sl@0: aResult = impl; sl@0: } sl@0: iMutex.Signal(); sl@0: return err; sl@0: } sl@0: sl@0: sl@0: void XSgDriverImpl::DeleteImage(XSgImageImplBase* aImage) sl@0: { sl@0: __ASSERT_DEBUG(iMutex.IsHeld(), Panic(ESgPanicMutexNotHeld)); sl@0: TInt i = iImages.FindInOrder(aImage, XSgImageImplBase::Compare); sl@0: __ASSERT_DEBUG(i != KErrNotFound, Panic(ESgPanicBadImageHandle)); sl@0: RHeap* prevHeap = User::SwitchHeap(iHeap); sl@0: iImages.Remove(i); sl@0: iImages.GranularCompress(); sl@0: User::SwitchHeap(prevHeap); sl@0: aImage->Delete(); sl@0: } sl@0: sl@0: sl@0: void XSgDriverImpl::DeleteImageCollection(XSgImageCollectionImpl* aImageCollection) sl@0: { sl@0: __ASSERT_DEBUG(iMutex.IsHeld(), Panic(ESgPanicMutexNotHeld)); sl@0: TInt i = iImageCollections.FindInAddressOrder(aImageCollection); sl@0: __ASSERT_DEBUG(i != KErrNotFound, Panic(ESgPanicBadImageCollectionHandle)); sl@0: RHeap* prevHeap = User::SwitchHeap(iHeap); sl@0: iImageCollections.Remove(i); sl@0: iImageCollections.GranularCompress(); sl@0: User::SwitchHeap(prevHeap); sl@0: aImageCollection->Delete(); sl@0: } sl@0: sl@0: sl@0: TBool XSgDriverImpl::CheckDrawable(const MSgResourceAdapter& aDrawable) const sl@0: { sl@0: iMutex.Wait(); sl@0: TInt i = iImages.Find(&static_cast(aDrawable)); sl@0: iMutex.Signal(); sl@0: return i != KErrNotFound; sl@0: } sl@0: sl@0: sl@0: TBool XSgDriverImpl::CheckImage(const MSgResourceAdapter& aImage) const sl@0: { sl@0: iMutex.Wait(); sl@0: TInt i = iImages.Find(&static_cast(aImage)); sl@0: iMutex.Signal(); sl@0: return i != KErrNotFound; sl@0: } sl@0: sl@0: sl@0: TBool XSgDriverImpl::CheckImageCollection(const MSgResourceAdapter& aImageCollection) const sl@0: { sl@0: iMutex.Wait(); sl@0: TInt i = iImageCollections.Find(&static_cast(aImageCollection)); sl@0: iMutex.Signal(); sl@0: return i != KErrNotFound; sl@0: } sl@0: sl@0: sl@0: TInt XSgDriverImpl::ResourceCount() const sl@0: { sl@0: iMutex.Wait(); sl@0: TInt count = 0; sl@0: for (TInt i = 0; i < iImages.Count(); ++i) sl@0: { sl@0: count += iImages[i]->RefCount(); sl@0: } sl@0: for (TInt i = 0; i < iImageCollections.Count(); ++i) sl@0: { sl@0: count += iImageCollections[i]->RefCount(); sl@0: } sl@0: iMutex.Signal(); sl@0: return count; sl@0: } sl@0: sl@0: sl@0: #ifdef _DEBUG sl@0: sl@0: void XSgDriverImpl::AllocMarkStart() sl@0: { sl@0: iMutex.Wait(); sl@0: iHeap->__DbgMarkStart(); sl@0: iMutex.Signal(); sl@0: } sl@0: sl@0: sl@0: void XSgDriverImpl::AllocMarkEnd(TInt aCount) sl@0: { sl@0: iMutex.Wait(); sl@0: TUint32 badCell = iHeap->__DbgMarkEnd(aCount); sl@0: iMutex.Signal(); sl@0: if (badCell != 0) sl@0: { sl@0: _LIT(KPanicCategoryFormat, "SGALLOC:%08x"); sl@0: TBuf<0x10> category; sl@0: category.Format(KPanicCategoryFormat, badCell); sl@0: User::Panic(category, 0); sl@0: } sl@0: } sl@0: sl@0: sl@0: void XSgDriverImpl::SetAllocFail(RAllocator::TAllocFail aType, TInt aRate) sl@0: { sl@0: iMutex.Wait(); sl@0: iHeap->__DbgSetAllocFail(aType, aRate); sl@0: iMutex.Signal(); sl@0: } sl@0: sl@0: #else sl@0: sl@0: void XSgDriverImpl::AllocMarkStart() sl@0: { sl@0: } sl@0: sl@0: sl@0: void XSgDriverImpl::AllocMarkEnd(TInt /*aCount*/) sl@0: { sl@0: } sl@0: sl@0: sl@0: void XSgDriverImpl::SetAllocFail(RAllocator::TAllocFail /*aType*/, TInt /*aRate*/) sl@0: { sl@0: } sl@0: sl@0: #endif sl@0: sl@0: sl@0: // MSgDriverAdapter::New() sl@0: sl@0: EXPORT_C TInt MSgDriverAdapter::New(MSgDriverAdapter*& aPtr) sl@0: { sl@0: RHeap* heap = UserHeap::ChunkHeap(NULL, 0, KSgMaxLocalChunkSize); sl@0: if (!heap) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: XSgDriverImpl* driverImpl = static_cast(heap->Alloc(sizeof(XSgDriverImpl))); sl@0: if (!driverImpl) sl@0: { sl@0: heap->Close(); sl@0: return KErrNoMemory; sl@0: } sl@0: new(driverImpl) XSgDriverImpl(heap); sl@0: TInt err = driverImpl->Construct(); sl@0: if (err != KErrNone) sl@0: { sl@0: driverImpl->Delete(); sl@0: return err; sl@0: } sl@0: aPtr = driverImpl; sl@0: return KErrNone; sl@0: }