Revise some of the compositor performance improvements to improve correctness.
Implement pixel blending using a variation of Jim Blinn's no-division blending algorithm.
Move transparency type simplification further up the composition code.
Remove some unnecessary fields.
Output to YUV implementation needs revision as it is actually converting from YUV (copy of source conversion code).
// 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