diff -r 000000000000 -r 5d03bc08d59c graphicsdeviceinterface/directgdi/src/directgdidriver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graphicsdeviceinterface/directgdi/src/directgdidriver.cpp Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,451 @@ +// 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 "directgdipaniccodes.h" // Included first to resolve dependency + +#include +#include +#include +#include +#include +#include +#include + +#include "directgdidriver.h" +#include "directgditypes.h" +#include "directgdidriverinternallibrary.inl" + +typedef TInt (*TDriverCreateFunction)(CDirectGdiDriverInternal*&, RLibrary); + +/** +Returns the singleton instance of CDirectGdiDriver for the calling thread. + +@return Pointer to an opened CDirectGdiDriver object else NULL if a CDirectGdiDriver had not been opened yet. +*/ +EXPORT_C CDirectGdiDriver* CDirectGdiDriver::Static() + { + return static_cast(Dll::Tls()); + } + +/** +Creates a new CDirectGdiDriver object if one has not already been created in this thread. +Performs any adaptation initialisation that is needed to allow the calling thread to use +functionality provided by the new DirectGDI interfaces. Calling this method multiple times +from the same client thread has no effect after the first call, other than to increase the +open count. + +@see CDirectGdiDriver::Close() + +@pre None. +@post The object reference counter is incremented. Adaptation resources for the +calling thread are created and initialised. The new DirectGDI interfaces are ready +to be used from the calling thread. + +@return KErrNone if successful, otherwise one of the system-wide error codes. +*/ +EXPORT_C TInt CDirectGdiDriver::Open() + { + TInt err = KErrNone; + CDirectGdiDriver* self = Static(); + + // Check we're not already opened + if (!self) + { + self = new CDirectGdiDriver(); + if (!self) + { + err = KErrNoMemory; + return err; + } + +#ifdef __WINS__ + // Dynamically load DirectGDI adapter library. + // Under WINS two dlls will be available - directgdiadapter_sw.dll and directgdiadapter_vg.dll + // Need to select which dll to load. The value of the keyword SYMBIAN_GRAPHICS_DIRECTGDI_USE + // in the epoc.ini file will determine the dll to load. + // If this keyword does not appear in the epoc.ini file, the software version of + // directgdiadapter will be loaded by default. + _LIT(KVgAdapterDllName, "directgdiadapter_vg.dll"); + _LIT(KSwAdapterDllName, "directgdiadapter_sw.dll"); + TBool useOpenVg = EFalse; + UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalBoolProperty, (TAny*)"symbian_graphics_directgdi_use_openvg", &useOpenVg); + TPtrC libraryName; + if(useOpenVg) + { + libraryName.Set(KVgAdapterDllName); + } + else + { + libraryName.Set(KSwAdapterDllName); + } + RLibrary lib; + err = lib.Load(libraryName); + if (err != KErrNone) + { + delete self; + return (err==KErrNotFound ? KErrNotSupported : err); + } + + // Create internal driver + err = self->CreateInternalDriver(lib); + if (err != KErrNone) + { + delete self; + lib.Close(); + return err; + } +#else + // Under armv5, the appropriate dll (software or vg) is determined at rom build time. + err = self->CreateInternalDriver(); + if (err != KErrNone) + { + delete self; + return err; + } +#endif + + // Store a pointer to the new driver instance in thread local storage: + err = Dll::SetTls(self); + if (err != KErrNone) + { + delete self; + } + } + + if (err == KErrNone) + { + ++(self->iOpenCount); + } + + return err; + } + +/** +Create the adaptation/internal object for this driver. + +@pre The adaptation/internal driver object has not been created yet. +@post The adaptation/internal object has been created. + +@return KErrNone if successful, otherwise one of the system-wide error codes. + */ +#ifdef __WINS__ +TInt CDirectGdiDriver::CreateInternalDriver(const RLibrary& aLibrary) + { + // Function at ordinal 1 creates new CDirectGdiDriverInternal + TDriverCreateFunction create = reinterpret_cast(aLibrary.Lookup(1)); + return create(iDriverInternal, aLibrary); + } +#else +TInt CDirectGdiDriver::CreateInternalDriver() + { + return CDirectGdiDriverInternal::New(iDriverInternal, RLibrary()); + } +#endif + +/** +Performs adaptation termination which is needed to release any internal resources +allocated by the calling thread. It will also perform an implicit Finish() by submitting +all outstanding requests from the calling thread. A DirectGDI client's thread that +uses the new DirectGDI interfaces must call this method at the end of its lifetime. + +@see CDirectGdiDriver::Open() + +@pre The driver is open from a call to Open(). +@post The object open count is decremented. If the open count reaches zero, any +adaptation resources allocated to the calling thread must be released, and the CDirectGdiDriver +object for the calling thread is destroyed. + +@panic DGDI 14, if Close() is called on a CDirectGdiDriver object that is not open. +*/ +EXPORT_C void CDirectGdiDriver::Close() + { + GRAPHICS_ASSERT_ALWAYS(iOpenCount > 0, EDirectGdiPanicDriverOpenCountError); + + if (--iOpenCount == 0) + { + // We call Finish() instead of Flush() because it will decrease the reference count + // of images used in DrawResource() (if any) and is guaranteed that it will complete. + // Flush() cannot guarantee completion so we can't decrement image reference counts. + Finish(); + + // Get the handle to the DLL used by iDriverInternal so that we can close + // it once iDriverInternal has been deleted. + RLibrary lib = iDriverInternal->Library(); + delete this; + lib.Close(); + + // Free the space we saved for the driver singleton pointer in thead local storage + Dll::FreeTls(); + } + } + +/** +Ensures all outstanding requests on the calling thread are submitted for processing. +The method immediately returns and does not wait until all outstanding requests are +completely processed. Clients can continue issuing rendering requests after calling +this method. + +@see CDirectGdiDriver::Finish() + +@pre CDirectGdiDriver object has been initialised for the calling thread. +@post All outstanding requests have been submitted for processing. +*/ +EXPORT_C void CDirectGdiDriver::Flush() + { + iDriverInternal->Flush(); + } + +/** +Ensures all outstanding rendering requests from the calling thread are submitted +and processed. This method will wait until all the outstanding rendering requests +have been completely processed. + +@see CDirectGdiDriver::Flush() + +@pre CDirectGdiDriver object has been initialised for the calling thread. +@post All outstanding requests have been completely processed. +*/ +EXPORT_C void CDirectGdiDriver::Finish() + { + iDriverInternal->Finish(); + } + +/** +Returns the first error code (as the result of calling any DirectGDI API), if any, +since the last call to this function or, if it has not previously been called, since +the CDirectGdiDriver was initialised. Calling this function clears the error code. + +@see CDirectGdiDriver::SetError(TInt) + +@pre CDirectGdiDriver object has been initialised for the calling thread. +@post The error code has been reset after being read. + +@return The first error code, if any, since the last call to this function or, + if it has not previously been called, since the CDirectGdiDriver was initialised. + KErrNone will indicate that no such error has occurred. +*/ +EXPORT_C TInt CDirectGdiDriver::GetError() + { + return iDriverInternal->GetError(); + } + + +/** +Sets the error code on the driver. If the error code is already set to a value other +than KErrNone, the error code will not be modified. + +@see CDirectGdiDriver::GetError() + +@param aErr The error code to set. + +@pre CDirectGdiDriver object has been initialised for the calling thread. +@post The error code has been set. +*/ +EXPORT_C void CDirectGdiDriver::SetError(TInt aErr) + { + iDriverInternal->SetError(aErr); + } + +/** +Retrieves a pointer to an instance of the requested extension interface implementation, if provided. + +@param aInterfaceId The globally unique identifier of the requested interface. +@param aInterface On return, holds the specified interface, or NULL if the interface cannot be found. + +@pre CDirectGdiDriver object has been initialised for the calling thread. + +@return KErrNone If the interface is supported, KErrExtensionNotSupported otherwise. + */ +EXPORT_C TInt CDirectGdiDriver::GetInterface(TUid aInterfaceId, TAny*& aInterface) + { + return iDriverInternal->GetInterface(aInterfaceId, aInterface); + } + +/** +CDirectGdiDriver private constructor as this class is singleton. + +@pre None. +@post Initialises the member reference counter to zero. +*/ +CDirectGdiDriver::CDirectGdiDriver() + { + } + +/** +CDirectGdiDriver default destructor. + +@pre None. +@post None. + +@panic DGDI 15, if the resource count is not zero. +*/ +CDirectGdiDriver::~CDirectGdiDriver() + { + GRAPHICS_ASSERT_ALWAYS(iOpenCount == 0, EDirectGdiPanicDriverDestructorOpenCountError); + delete iDriverInternal; + } + +/** +Delegates the call to the CDirectGdiDriverInternal object, which creates a DirectGDI +adaptation-specific resource from the given drawable resource so it can be drawn +using the DirectGDI rendering API. + +@see CloseDrawableSource() + +@param aRDirectGdiDrawableSource The RDirectGdiDrawableSource object to be created +@param aRSgDrawable The RSgDrawable object to use when creating aRDirectGdiDrawableSource + +@pre CDirectGdiDriver object has been initialised from the calling thread. +@post The DirectGDI adaptation-specific resource that is bound to the given +drawable resource is created and this handle is now associated with it. The reference +counter on the drawable resource is incremented. The CDirectGdiDriver for this thread +is now aware of and owns the adaptation specific resource. + +@return KErrNone if successful, KErrNotSupported if the drawable resource is not +created with the correct usage (ESgUsageDirectGdiSource must be set), otherwise one of the system-wide error codes. + +@panic DGDI 19, if this handle is already associated with a DirectGDI adaptation-specific drawable resource. +@panic DGDI 20, if the drawable resource is not valid. +*/ +TInt CDirectGdiDriver::CreateDrawableSource(RDirectGdiDrawableSource& aRDirectGdiDrawableSource, const RSgDrawable& aRSgDrawable) + { + GRAPHICS_ASSERT_ALWAYS(aRDirectGdiDrawableSource.Handle() == KNullHandle, EDirectGdiPanicDrawableSourceAlreadyExists); + + if(aRSgDrawable.DrawableType() == KSgImageTypeUid) + {// make sure that drawable was created with the flag ESgUsageDirectGdiSource + RSgImage *image = (RSgImage*) &aRSgDrawable; + TSgImageInfo info; + TInt err = image ->GetInfo (info); + GRAPHICS_ASSERT_ALWAYS(err == KErrNone, EDirectGdiPanicImageSourceInfoError); + + if (!(info.iUsage & ESgUsageDirectGdiSource)) + { + return KErrNotSupported; + } + } + return iDriverInternal->CreateDrawableSource(aRDirectGdiDrawableSource.iHandle, aRSgDrawable); + } + +/** +Delegates call to the CDirectGdiDriverInternal object, which destroys the DirectGDI +adaptation-specific resource associated with this handle. Calling this method on a +handle that is not associated with any DirectGDI adaptation specific resource will +do nothing. Once Close() is called, this handle can be reused. + +@see CreateDrawableSource() + +@param aSource The RDirectGdiDrawableSource object. + +@pre CDirectGdiDriver object has been initialised from the calling thread. +@post The DirectGDI specific resource associated with this handle will be +destroyed (at any time preferred by the adaptation). This handle is no longer +associated with a DirectGDI specific resource. The reference counter of the +underlying non-image resource is decremented. +*/ +void CDirectGdiDriver::CloseDrawableSource(RDirectGdiDrawableSource& aSource) + { + iDriverInternal->CloseDrawableSource(aSource.iHandle); + } + +/** +Delegates call to the CDirectGdiDriverInternal object, which creates a DirectGDI +adaptation-specific resource from the given image resource so it can be used as a +target of DirectGDI rendering. + +@see CloseImageTarget() + +@param aTarget The RDirectGdiImageTarget object. +@param aImage The RSgImage object. + +@pre CDirectGdiDriver object has been initialised from the calling thread. +The image resource has been fully constructed and created with the correct usage +that allows it to be used as a DirectGDI target. + +@post The DirectGDI adaptation-specific resource that is bound to the given image +resource is created and this handle is now associated with it. The reference counter +on the image resource is incremented. + +@return KErrNone if successful, KErrNotSupported if the image resource is not +created with the correct usage, otherwise one of the system-wide error codes. + +@panic DGDI 17, if this handle is already associated with a DirectGDI adaptation-specific resource. +@panic DGDI 21, if the image resource is not valid. +*/ +TInt CDirectGdiDriver::CreateImageTarget(RDirectGdiImageTarget& aTarget, const RSgImage& aImage) + { + GRAPHICS_ASSERT_ALWAYS(aTarget.Handle() == KNullHandle, EDirectGdiPanicImageTargetAlreadyExists); + TSgImageInfo info; + TInt err = aImage.GetInfo(info); + GRAPHICS_ASSERT_ALWAYS(err == KErrNone, EDirectGdiPanicImageTargetInfoError); + + if (!(info.iUsage & ESgUsageDirectGdiTarget)) + { + return KErrNotSupported; + } + return iDriverInternal->CreateImageTarget(aTarget.iHandle, aImage); + } + +/** +Delegates call to the CDirectGdiDriverInternal object, which destroys the DirectGDI +adaptation specific resource associated with this handle. Calling this method on a +handle that is not associated with any DirectGDI adaptation specific resource will +do nothing. Once Close() is called, this handle can be reused. + +@see CreateImageTarget() + +@param aTarget The RDirectGdiImageTarget object. + +@pre CDirectGdiDriver object has been initialised from the calling thread. + +@post The DirectGDI specific resource associated with this handle will be destroyed +(at any time preferred by the adaptation). This handle is no longer associated with +a DirectGDI specific resource. The reference counter of the underlying image +resource is decremented. +*/ +void CDirectGdiDriver::CloseImageTarget(RDirectGdiImageTarget& aTarget) + { + iDriverInternal->CloseImageTarget(aTarget.iHandle); + } + +/** +Delegates call to the CDirectGdiDriverInternal object, which creates a +MDirectGdiEngine object. + +@param aEngine The MDirectGdiEngine object. + +@pre CDirectGdiDriver object has been initialised from the calling thread. +@post None. + +@return KErrNone if successful, otherwise one of the system-wide error codes. +*/ +TInt CDirectGdiDriver::CreateEngine(MDirectGdiEngine*& aEngine) + { + return iDriverInternal->CreateEngine(aEngine); + } + +/** +Delegates call to the CDirectGdiDriverInternal object, which destroys a +MDirectGdiEngine object. + +@param aEngine The MDirectGdiEngine object. + +@pre CDirectGdiDriver object has been initialised from the calling thread. +@post None. +*/ +void CDirectGdiDriver::DestroyEngine(MDirectGdiEngine* aEngine) + { + iDriverInternal->DestroyEngine(aEngine); + } +