// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
//
#include "sgimageimpl.h"
#include "sgresourceinternal.h"
// TSgImageMetaData
TSgImageMetaData::TSgImageMetaData(const TSgImageInfo& aInfo, TArray<TSgPixelFormatTableEntry> aPixelFormatTable, TBool aIsCached)
: iCreatorProcess(RProcess().Id()),
iSizeInPixels(aInfo.iSizeInPixels),
iPixelFormat(aInfo.iPixelFormat),
iRequestedUsage(aInfo.iUsage),
iPotentialUsage(0),
iShareable(aInfo.iShareable),
iCpuAccess(aInfo.iCpuAccess),
iScreenId(aInfo.iScreenId),
iIsCached(aIsCached)
{
TUint32 usageMask = (aInfo.iUsage & KSgUsageAllSources ? KSgUsageAllSources : 0)
| (aInfo.iUsage & KSgUsageAllTargets ? KSgUsageAllTargets : 0);
TInt n = aPixelFormatTable.Count();
for (TInt i = 0; i < n; ++i)
{
const TSgPixelFormatTableEntry& entry = aPixelFormatTable[i];
if (entry.IsMatchIgnoringUsage(aInfo))
{
iPotentialUsage |= entry.iUsage & usageMask;
}
}
}
void TSgImageMetaData::GetInfo(TSgImageInfo& aInfo, TBool aGetPotentialUsage) const
{
aInfo.iSizeInPixels = iSizeInPixels;
aInfo.iPixelFormat = iPixelFormat;
aInfo.iUsage = aGetPotentialUsage ? iPotentialUsage : iRequestedUsage;
aInfo.iShareable = iShareable;
aInfo.iCpuAccess = iCpuAccess;
aInfo.iScreenId = iScreenId;
}
// XSgImageImplBase
XSgImageImplBase::XSgImageImplBase(const XSgImageImplBase& aImage, TUint32 aFlags)
: XSgBase(aImage.iDriverImpl)
{
__ASSERT_DEBUG(iDriverImpl.IsMutexHeld(), Panic(ESgPanicMutexNotHeld));
iId = aImage.iId;
iId.iId[KSgImageIdFlagsIndex] = aFlags;
aImage.iState->IncRefCount();
iState = aImage.iState;
}
XSgImageImplBase::~XSgImageImplBase()
{
__ASSERT_DEBUG(iDriverImpl.IsMutexHeld(), Panic(ESgPanicMutexNotHeld));
if (iState && iState->DecRefCount() == 0)
{
Unmap();
iState->Delete();
}
}
TInt XSgImageImplBase::Compare(const TSgDrawableId* aId, const XSgImageImplBase& aImage)
{
return Mem::Compare(reinterpret_cast<const TUint8*>(aId), sizeof(TSgDrawableId),
reinterpret_cast<const TUint8*>(&aImage.Id()), sizeof(TSgDrawableId));
}
TInt XSgImageImplBase::Compare(const XSgImageImplBase& aImage1, const XSgImageImplBase& aImage2)
{
return Compare(&aImage1.Id(), aImage2);
}
TInt XSgImageImplBase::CompareIgnoringFlags(const TSgDrawableId* aId, const XSgImageImplBase& aImage)
{
return Mem::Compare(reinterpret_cast<const TUint8*>(aId), sizeof(TSgDrawableId) - sizeof(TUint32),
reinterpret_cast<const TUint8*>(&aImage.Id()), sizeof(TSgDrawableId) - sizeof(TUint32));
}
void XSgImageImplBase::Close()
{
XSgDriverImpl& driverImpl = iDriverImpl;
driverImpl.Wait();
if (DecRefCount() == 0)
{
driverImpl.DeleteImage(this);
}
driverImpl.Signal();
}
const TSgDrawableId& XSgImageImplBase::Id() const
{
return iId;
}
TUid XSgImageImplBase::DrawableType() const
{
return KSgImageTypeUid;
}
TInt XSgImageImplBase::GetInterface(TUid aInterfaceUid, TAny*& aInterfacePtr)
{
if (aInterfaceUid.iUid == MSgImage_Sw::EInterfaceUid)
{
aInterfacePtr = static_cast<MSgImage_Sw*>(this);
return KErrNone;
}
return KErrExtensionNotSupported;
}
TInt XSgImageImplBase::GetInfo(TSgImageInfo& aInfo) const
{
iState->MetaData().GetInfo(aInfo, iId.iId[KSgImageIdFlagsIndex] & ESgDoNotRestrictUsage);
return iState->GetUserAttributes(aInfo.iUserAttributes, aInfo.iUserAttributeCount);
}
TInt XSgImageImplBase::MapReadOnly(const TAny*& aDataAddress, TInt& aDataStride)
{
TInt err = iState->BeginDataAccess(ESgCpuAccessReadOnly, ETrue);
if (err != KErrNone)
{
return err;
}
aDataAddress = iState->DataAddress();
aDataStride = iState->DataStride();
return KErrNone;
}
TInt XSgImageImplBase::MapWriteOnly(TAny*& aDataAddress, TInt& aDataStride)
{
TInt err = iState->BeginDataAccess(ESgCpuAccessWriteOnly, ETrue);
if (err != KErrNone)
{
return err;
}
aDataAddress = iState->DataAddress();
aDataStride = iState->DataStride();
return KErrNone;
}
TInt XSgImageImplBase::MapReadWrite(TAny*& aDataAddress, TInt& aDataStride)
{
TInt err = iState->BeginDataAccess(ESgCpuAccessReadWrite, ETrue);
if (err != KErrNone)
{
return err;
}
aDataAddress = iState->DataAddress();
aDataStride = iState->DataStride();
return KErrNone;
}
TInt XSgImageImplBase::Unmap()
{
return iState->EndDataAccess(ETrue);
}
TAny* XSgImageImplBase::DataAddress() const
{
return iState->DataAddress();
}
TInt XSgImageImplBase::DataStride() const
{
return iState->DataStride();
}
TInt XSgImageImplBase::BeginDataAccess(TSgCpuAccess aCpuAccess)
{
return iState->BeginDataAccess(aCpuAccess, EFalse);
}
TInt XSgImageImplBase::EndDataAccess()
{
return iState->EndDataAccess(EFalse);
}
TInt XSgImageImplBase::SetData(const TAny* aDataAddress, TInt aDataStride)
{
if (aDataAddress)
{
TInt err = BeginDataAccess(ESgCpuAccessWriteOnly);
if (err != KErrNone)
{
return err;
}
const TSgImageMetaData& metaData = iState->MetaData();
const TAny* src = aDataAddress;
TAny* trg = iState->DataAddress();
TInt dataStride = iState->DataStride();
TInt minDataStride = SgMinDataStride(metaData.iSizeInPixels.iWidth, metaData.iPixelFormat);
__ASSERT_DEBUG(minDataStride > 0, Panic(ESgPanicResourceAdapterGeneral));
for (TInt y = 0; y < metaData.iSizeInPixels.iHeight; ++y)
{
Mem::Copy(trg, src, minDataStride);
src = PtrAdd(src, aDataStride);
trg = PtrAdd(trg, dataStride);
}
EndDataAccess();
}
return KErrNone;
}
TInt XSgImageStateBase::BeginDataAccess(TSgCpuAccess aCpuAccess, TBool aIsUserAccess)
{
if (aCpuAccess == ESgCpuAccessNone)
{
return KErrArgument;
}
const TSgImageMetaData& metaData = MetaData();
if (aIsUserAccess && (~metaData.iCpuAccess & aCpuAccess))
{
return KErrAccessDenied;
}
if (aIsUserAccess && metaData.iCreatorProcess != RProcess().Id())
{
return KErrPermissionDenied;
}
iDriverImpl.Wait();
if (iCpuAccess != ESgCpuAccessNone)
{
iDriverImpl.Signal();
return KErrInUse;
}
iCpuAccess = aCpuAccess;
iIsUserAccess = aIsUserAccess;
iDriverImpl.Signal();
return KErrNone;
}
TInt XSgImageStateBase::EndDataAccess(TBool aIsUserAccess)
{
iDriverImpl.Wait();
if (iCpuAccess == ESgCpuAccessNone || iIsUserAccess != aIsUserAccess)
{
iDriverImpl.Signal();
return KErrGeneral;
}
iCpuAccess = ESgCpuAccessNone;
iIsUserAccess = EFalse;
iDriverImpl.Signal();
return KErrNone;
}
#ifndef SYMBIAN_GRAPHICS_USE_GPU
// XSgImageImpl_SwLocal
TInt XSgImageImpl_SwLocal::New(XSgImageImpl_SwLocal*& aPtr, XSgDriverImpl& aDriverImpl, const TSgDrawableId& aId,
const TSgImageInfo& aInfo, const TAny* aDataAddress, TInt aDataStride)
{
aPtr = static_cast<XSgImageImpl_SwLocal*>(aDriverImpl.Alloc(sizeof(XSgImageImpl_SwLocal)));
if (!aPtr)
{
return KErrNoMemory;
}
new(aPtr) XSgImageImpl_SwLocal(aDriverImpl, aId);
TInt err = aPtr->Construct(aInfo, aDataAddress, aDataStride);
if (err != KErrNone)
{
aPtr->Delete();
aPtr = NULL;
}
return err;
}
TInt XSgImageImpl_SwLocal::New(XSgImageImpl_SwLocal*& aPtr, const XSgImageImpl_SwLocal& aImage, TUint32 aFlags)
{
aPtr = static_cast<XSgImageImpl_SwLocal*>(aImage.iDriverImpl.Alloc(sizeof(XSgImageImpl_SwLocal)));
if (!aPtr)
{
return KErrNoMemory;
}
new(aPtr) XSgImageImpl_SwLocal(aImage, aFlags);
return KErrNone;
}
TInt XSgImageImpl_SwLocal::Construct(const TSgImageInfo& aInfo, const TAny* aDataAddress, TInt aDataStride)
{
XSgImageState_SwLocal* state;
TInt err = XSgImageState_SwLocal::New(state, iDriverImpl, aInfo);
if (err != KErrNone)
{
return err;
}
state->IncRefCount();
iState = state;
return SetData(aDataAddress, aDataStride);
}
// XSgImageState_SwLocal
TInt XSgImageState_SwLocal::New(XSgImageState_SwLocal*& aPtr, XSgDriverImpl& aDriverImpl, const TSgImageInfo& aInfo)
{
TInt dataStride = Align4(SgMinDataStride(aInfo.iSizeInPixels.iWidth, aInfo.iPixelFormat));
TInt size = _FOFF(XSgImageState_SwLocal, iUserAttributes) + aInfo.iUserAttributeCount * sizeof(TSgUserAttribute) + dataStride * aInfo.iSizeInPixels.iHeight;
aPtr = static_cast<XSgImageState_SwLocal*>(aDriverImpl.Alloc(size));
if (!aPtr)
{
return KErrNoMemory;
}
new(aPtr) XSgImageState_SwLocal(aDriverImpl, aInfo, dataStride);
return KErrNone;
}
XSgImageState_SwLocal::XSgImageState_SwLocal(XSgDriverImpl& aDriverImpl, const TSgImageInfo& aInfo, TInt aDataStride)
: XSgImageStateBase(aDriverImpl, aDataStride), iMetaData(aInfo, aDriverImpl.PixelFormatTable())
{
iUserAttributeCount = aInfo.iUserAttributeCount;
Mem::Copy(iUserAttributes, aInfo.iUserAttributes, aInfo.iUserAttributeCount * sizeof(TSgUserAttribute));
}
const TSgImageMetaData& XSgImageState_SwLocal::MetaData() const
{
return iMetaData;
}
TInt XSgImageState_SwLocal::GetUserAttributes(TSgUserAttribute* aUserAttributes, TInt aUserAttributeCount) const
{
for (TInt i = 0; i < aUserAttributeCount; ++i)
{
TBool found = EFalse;
for (TInt j = 0; j < iUserAttributeCount; ++j)
{
if (aUserAttributes[i].iUid == iUserAttributes[j].iUid)
{
aUserAttributes[i].iValue = iUserAttributes[j].iValue;
found = ETrue;
break;
}
}
if (!found)
{
return KErrNotFound;
}
}
return KErrNone;
}
TAny* XSgImageState_SwLocal::DataAddress() const
{
//__ASSERT_DEBUG(iCpuAccess != ESgCpuAccessNone, ::Panic(ESgPanicNoCpuAccess));
return (TAny*)PtrAdd(iUserAttributes, iUserAttributeCount * sizeof(TSgUserAttribute));
}
#endif
// XSgImageImpl_SurfaceManager
TInt XSgImageImpl_SurfaceManager::New(XSgImageImpl_SurfaceManager*& aPtr, XSgDriverImpl& aDriverImpl,
const TSgImageInfo& aInfo, TBool aIsCached, const TAny* aDataAddress, TInt aDataStride)
{
aPtr = static_cast<XSgImageImpl_SurfaceManager*>(aDriverImpl.Alloc(sizeof(XSgImageImpl_SurfaceManager)));
if (!aPtr)
{
return KErrNoMemory;
}
new(aPtr) XSgImageImpl_SurfaceManager(aDriverImpl);
TInt err = aPtr->Construct(aInfo, aIsCached, aDataAddress, aDataStride);
if (err != KErrNone)
{
aPtr->Delete();
aPtr = NULL;
}
return err;
}
TInt XSgImageImpl_SurfaceManager::New(XSgImageImpl_SurfaceManager*& aPtr, XSgDriverImpl& aDriverImpl, const TSgDrawableId& aId)
{
aPtr = static_cast<XSgImageImpl_SurfaceManager*>(aDriverImpl.Alloc(sizeof(XSgImageImpl_SurfaceManager)));
if (!aPtr)
{
return KErrNoMemory;
}
new(aPtr) XSgImageImpl_SurfaceManager(aDriverImpl, aId);
TInt err = aPtr->Construct(aId);
if (err != KErrNone)
{
aPtr->Delete();
aPtr = NULL;
}
return err;
}
TInt XSgImageImpl_SurfaceManager::New(XSgImageImpl_SurfaceManager*& aPtr, const XSgImageImpl_SurfaceManager& aImage, TUint32 aFlags)
{
aPtr = static_cast<XSgImageImpl_SurfaceManager*>(aImage.iDriverImpl.Alloc(sizeof(XSgImageImpl_SurfaceManager)));
if (!aPtr)
{
return KErrNoMemory;
}
new(aPtr) XSgImageImpl_SurfaceManager(aImage, aFlags);
return KErrNone;
}
TInt XSgImageImpl_SurfaceManager::Construct(const TSgImageInfo& aInfo, TBool aIsCached, const TAny* aDataAddress, TInt aDataStride)
{
XSgImageState_SurfaceManager* state;
TInt err = XSgImageState_SurfaceManager::New(state, iDriverImpl, aInfo, aIsCached);
if (err != KErrNone)
{
return err;
}
Mem::Copy(&iId, &state->SurfaceId(), sizeof(TSurfaceId));
state->IncRefCount();
iState = state;
return SetData(aDataAddress, aDataStride);
}
TInt XSgImageImpl_SurfaceManager::Construct(const TSgDrawableId& aId)
{
XSgImageState_SurfaceManager* state;
TInt err = XSgImageState_SurfaceManager::New(state, iDriverImpl, aId);
if (err != KErrNone)
{
return err;
}
state->IncRefCount();
iState = state;
return KErrNone;
}
TInt XSgImageImpl_SurfaceManager::GetInterface(TUid aInterfaceUid, TAny*& aInterfacePtr)
{
if (aInterfaceUid.iUid == MSgImage_Chunk::EInterfaceUid)
{
aInterfacePtr = static_cast<MSgImage_Chunk*>(this);
return KErrNone;
}
return XSgImageImplBase::GetInterface(aInterfaceUid, aInterfacePtr);
}
const RChunk& XSgImageImpl_SurfaceManager::DataChunk() const
{
return static_cast<XSgImageState_SurfaceManager*>(iState)->DataChunk();
}
TInt XSgImageImpl_SurfaceManager::DataOffset() const
{
return static_cast<XSgImageState_SurfaceManager*>(iState)->DataOffset();
}
TInt XSgImageImpl_SurfaceManager::DataStride() const
{
return iState->DataStride();
}
// XSgImageState_SurfaceManager
TInt XSgImageState_SurfaceManager::New(XSgImageState_SurfaceManager*& aPtr, XSgDriverImpl& aDriverImpl, const TSgImageInfo& aInfo, TBool aIsCached)
{
aPtr = static_cast<XSgImageState_SurfaceManager*>(aDriverImpl.Alloc(sizeof(XSgImageState_SurfaceManager)));
if (!aPtr)
{
return KErrNoMemory;
}
new(aPtr) XSgImageState_SurfaceManager(aDriverImpl);
TInt err = aPtr->Construct(aInfo, aIsCached);
if (err != KErrNone)
{
aPtr->Delete();
aPtr = NULL;
}
return err;
}
TInt XSgImageState_SurfaceManager::New(XSgImageState_SurfaceManager*& aPtr, XSgDriverImpl& aDriverImpl, const TSgDrawableId& aId)
{
aPtr = static_cast<XSgImageState_SurfaceManager*>(aDriverImpl.Alloc(sizeof(XSgImageState_SurfaceManager)));
if (!aPtr)
{
return KErrNoMemory;
}
new(aPtr) XSgImageState_SurfaceManager(aDriverImpl);
TInt err = aPtr->Construct(aId);
if (err != KErrNone)
{
aPtr->Delete();
aPtr = NULL;
}
return err;
}
TInt XSgImageState_SurfaceManager::Construct(const TSgImageInfo& aInfo, TBool aIsCached)
{
TInt maxNumberOfHints;
TInt err;
err=iDriverImpl.GetSurfaceManagerAttrib(RSurfaceManager::EMaxNumberOfHints,maxNumberOfHints);
if (err!=KErrNone)
{
return err;
}
if (aInfo.iUserAttributeCount > maxNumberOfHints)
{
return KErrOverflow;
}
RSurfaceManager::THintPair* hints = new RSurfaceManager::THintPair[aInfo.iUserAttributeCount];
if(!hints)
{
return KErrNoMemory;
}
RSurfaceManager::TSurfaceCreationAttributesBuf reqs;
reqs().iSurfaceHints = hints;
reqs().iHintCount = aInfo.iUserAttributeCount;
reqs().iSize = aInfo.iSizeInPixels;
reqs().iBuffers = 1;
reqs().iPixelFormat = aInfo.iPixelFormat;
reqs().iStride = SgAlignedDataStride(aInfo.iSizeInPixels.iWidth, aInfo.iPixelFormat);
reqs().iOffsetToFirstBuffer = SgOffsetToFirstBuffer(sizeof(TSgImageMetaData));
reqs().iAlignment = 4;
reqs().iContiguous = EFalse;
reqs().iCacheAttrib = aIsCached ? RSurfaceManager::ECached : RSurfaceManager::ENotCached;
reqs().iOffsetBetweenBuffers = SgOffsetBetweenBuffers(reqs().iStride, aInfo.iSizeInPixels.iHeight);
reqs().iMappable = ETrue;
for (TInt i = 0; i < aInfo.iUserAttributeCount; ++i)
{
reqs().iSurfaceHints[i].iKey = aInfo.iUserAttributes[i].iUid;
reqs().iSurfaceHints[i].iValue = aInfo.iUserAttributes[i].iValue;
reqs().iSurfaceHints[i].iMutable = EFalse;
}
TSurfaceId surfaceId;
err = iDriverImpl.CreateSurface(reqs, surfaceId);
delete[] hints;
hints = NULL;
reqs().iSurfaceHints = NULL;
if (err != KErrNone)
{
return err;
}
iSurfaceId = surfaceId;
RSurfaceManager::TInfoBuf info;
err = iDriverImpl.SurfaceInfo(surfaceId, info);
if (err != KErrNone)
{
return err;
}
err=iDriverImpl.GetBufferOffset(surfaceId,0,iDataOffset);
if (err != KErrNone)
{
return err;
}
iDataStride = info().iStride;
RChunk chunk;
err = iDriverImpl.MapSurface(surfaceId, chunk);
if (err != KErrNone)
{
return err;
}
iDataChunk = chunk;
new(chunk.Base()) TSgImageMetaData(aInfo, iDriverImpl.PixelFormatTable(), aIsCached);
return err;
}
TInt XSgImageState_SurfaceManager::Construct(const TSgDrawableId& aId)
{
const TSgImageId_SurfaceManager& id_SurfaceManager = reinterpret_cast<const TSgImageId_SurfaceManager&>(aId);
if (id_SurfaceManager.iBufferIndex < 0)
{
return KErrNotFound;
}
if (id_SurfaceManager.iMetaDataIndex < 0)
{
return KErrNotFound;
}
TInt err = iDriverImpl.OpenSurface(id_SurfaceManager.iSurfaceId);
if (err != KErrNone)
{
return err;
}
iSurfaceId = id_SurfaceManager.iSurfaceId;
RSurfaceManager::TInfoBuf info;
err = iDriverImpl.SurfaceInfo(id_SurfaceManager.iSurfaceId, info);
if (err != KErrNone)
{
return err;
}
iDataStride = info().iStride;
if (id_SurfaceManager.iBufferIndex >= info().iBuffers)
{
return KErrNotFound;
}
iBufferIndex = id_SurfaceManager.iBufferIndex;
TInt offsetToFirstBuffer;
err=iDriverImpl.GetBufferOffset(id_SurfaceManager.iSurfaceId,0,offsetToFirstBuffer);
if (err != KErrNone)
{
return err;
}
if ((id_SurfaceManager.iMetaDataIndex + 1) * sizeof(TSgImageMetaData) > offsetToFirstBuffer)
{
return KErrNotFound;
}
iMetaDataOffset = id_SurfaceManager.iMetaDataIndex * sizeof(TSgImageMetaData);
RChunk chunk;
err = iDriverImpl.MapSurface(id_SurfaceManager.iSurfaceId, chunk);
if (err != KErrNone)
{
return err;
}
iDataChunk = chunk;
err=iDriverImpl.GetBufferOffset(id_SurfaceManager.iSurfaceId,id_SurfaceManager.iBufferIndex,iDataOffset);
return err;
}
XSgImageState_SurfaceManager::~XSgImageState_SurfaceManager()
{
if (!iSurfaceId.IsNull())
{
iDriverImpl.CloseSurface(iSurfaceId);
iDataChunk.Close();
}
}
const TSgImageMetaData& XSgImageState_SurfaceManager::MetaData() const
{
return *reinterpret_cast<TSgImageMetaData*>(iDataChunk.Base() + iMetaDataOffset);
}
TInt XSgImageState_SurfaceManager::GetUserAttributes(TSgUserAttribute* aUserAttributes, TInt aUserAttributeCount) const
{
for (TInt i = 0; i < aUserAttributeCount; ++i)
{
RSurfaceManager::THintPair hint;
hint.iKey = aUserAttributes[i].iUid;
TInt err = iDriverImpl.GetSurfaceHint(iSurfaceId, hint);
if (err != KErrNone)
{
return err;
}
aUserAttributes[i].iValue = hint.iValue;
}
return KErrNone;
}
TAny* XSgImageState_SurfaceManager::DataAddress() const
{
#ifdef SYMBIAN_GRAPHICS_AUTOFLUSH_CACHE
__ASSERT_DEBUG(iCpuAccess != ESgCpuAccessNone, ::Panic(ESgPanicNoCpuAccess));
#endif
return iDataChunk.Base() + iDataOffset;
}
#ifdef SYMBIAN_GRAPHICS_AUTOFLUSH_CACHE
TInt XSgImageState_SurfaceManager::BeginDataAccess(TSgCpuAccess aCpuAccess, TBool aIsUserAccess)
{
TInt err = XSgImageStateBase::BeginDataAccess(aCpuAccess, aIsUserAccess);
if (err != KErrNone)
{
return err;
}
if (aCpuAccess != ESgCpuAccessWriteOnly && MetaData().iIsCached && (MetaData().iPotentialUsage & KSgUsageAllTargets))
{
// Cache::SyncMemoryAfterDmaRead() cannot fail so the following should not fail if the arguments are correct
err = iDriverImpl.SynchronizeCache(iSurfaceId, iBufferIndex, RSurfaceManager::ESyncAfterNonCPUWrite);
__ASSERT_DEBUG(err == KErrNone, Panic(ESgPanicResourceAdapterGeneral));
}
return KErrNone;
}
TInt XSgImageState_SurfaceManager::EndDataAccess(TBool aIsUserAccess)
{
TSgCpuAccess prevCpuAccess = iCpuAccess;
TInt err = XSgImageStateBase::EndDataAccess(aIsUserAccess);
if (err != KErrNone)
{
return err;
}
if (prevCpuAccess != ESgCpuAccessReadOnly && MetaData().iIsCached)
{
// Cache::SyncMemoryBeforeDmaWrite() cannot fail so the following should not fail if the arguments are correct
err = iDriverImpl.SynchronizeCache(iSurfaceId, iBufferIndex, RSurfaceManager::ESyncBeforeNonCPURead);
__ASSERT_DEBUG(err == KErrNone, Panic(ESgPanicResourceAdapterGeneral));
}
return KErrNone;
}
#endif