graphicsdeviceinterface/directgdiadaptation/hwsrc/directgdiimagetargetimpl.cpp
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/directgdiadaptation/hwsrc/directgdiimagetargetimpl.cpp	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,206 @@
+// 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 "directgdiadapter.h"
+#include "directgdiimagetargetimpl.h"
+#include "directgdidriverimpl.h"
+#include "confighelper.h"
+
+/**
+Constructs a CDirectGdiImageTargetImpl.
+@param	aDriver		The driver implementation which created this target.
+*/
+CDirectGdiImageTargetImpl::CDirectGdiImageTargetImpl(CDirectGdiDriverImpl& aDriver) :
+	iDriver(aDriver),
+	iSurface(EGL_NO_SURFACE),
+	iContext(EGL_NO_CONTEXT)
+	{
+	}
+
+/** 
+Destructor for CDirectGdiImageTargetImpl - Destroys the EGL surface.
+It will remove itself from the driver's image target array, before deleting itself.
+*/
+CDirectGdiImageTargetImpl::~CDirectGdiImageTargetImpl()
+{	
+#ifdef _DEBUG_DIRECTGDI
+	GRAPHICS_LOG_DEBUG("Destroying CDirectGdiImageTargetImpl");
+#endif
+	if (iDriver.IsCurrentTarget(this))
+		{
+		iDriver.SetCurrentTarget(NULL);
+		}
+	
+	if (iSurface != EGL_NO_SURFACE)
+		{
+		// If the surface being deleted is current to EGL, it will defer the destruction of the surface 
+		// until something else is made current. Destruction would rather be immediate so that the 
+		// associated native pixmap can be used again. In that case, the surface is dereferenced by making 
+		// something else current.
+		if (eglGetCurrentSurface(EGL_DRAW) == iSurface)
+			{
+			eglMakeCurrent(iDriver.EglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);			
+			}
+		
+		eglDestroySurface(iDriver.EglDisplay(), iSurface);	
+		}
+	iDriver.UnregisterTargetImage(*this);	
+}
+
+/**
+Two-phase construction of a CDirectGdiImageTargetImpl object.
+@param aImage On success, holds a pointer to the newly-created image.
+@param aDriver The driver to register this image with.
+@param aSgImage The RSgImage which this image will be based upon.
+@param aContexts A hash map of already-created EGLContext/Config pairs. 
+@param aConfigs A hash map of EGLConfig/Attribute pairs.
+@param aSharedContext A reference to the current shared context.
+@return KErrNone if successful, KErrNoMemory if not enough memory could be allocated, otherwise a return
+        value from Construct().
+*/
+TInt CDirectGdiImageTargetImpl::New(CDirectGdiImageTargetImpl*& aImage, 
+		CDirectGdiDriverImpl& aDriver, 
+		const RSgImage& aSgImage, 
+		RHashMap<TInt, EGLContext>& aContexts, 
+		RHashMap<TInt, EGLConfig>& aConfigs, 
+		EGLContext& aSharedContext)
+	{
+	CDirectGdiImageTargetImpl* image = new CDirectGdiImageTargetImpl(aDriver);
+	if (!image)
+		return KErrNoMemory;
+	TInt err = image->Construct(aSgImage, aContexts, aConfigs, aSharedContext);
+	if (err == KErrNone)
+		aImage = image;
+	else 
+		delete image;
+	return err;
+	}
+
+/**
+Gets the supplied image structure and sets the internal data. It creates a new image target by creating 
+an EGL context corresponding to a pixel type and an EGL config (if the EGLContext is not already created). 
+If it was already there, it fetches the EGL context from the hash map. Creates an EGL surface that is then 
+set for use by the new target object. Targets that are successfully created are added to an array of targets 
+so that they can be closed and deleted correctly at a later stage.
+
+@param aSgImage The RSgImage to create the source image from.
+@param aContexts A hash map of already-created EGLContext/Config pairs. 
+@param aConfigs A hash map of EGLConfig/Attribute pairs.
+@param aSharedContext A reference to the current shared context.
+@return KErrNone if successful, otherwise an error from CDirectGdiImageRef::Construct().
+
+@panic DGDIAdapter 41, if a matching EGL config is not found for this RSgImage.
+@panic DGDIAdapter 42, if an EGLSurface cannot be created.
+@panic DGDIAdapter 43, if an EGLContext cannot be created.
+*/ 
+TInt CDirectGdiImageTargetImpl::Construct(const RSgImage& aSgImage, RHashMap<TInt, EGLContext>& aContexts, RHashMap<TInt, EGLConfig>& aConfigs, EGLContext& aSharedContext)
+	{
+	TSgImageInfo info;
+	EGLSurface surface = EGL_NO_SURFACE;
+	EGLContext* context = NULL;
+	EGLContext newContext = EGL_NO_CONTEXT;
+	TBool createdNewContext = EFalse;
+	TInt pixmapAttribs = 0;
+	const EGLDisplay display = iDriver.EglDisplay();
+	
+	TInt err = CDirectGdiImageRef::Construct(aSgImage);
+			
+	if (err == KErrNone)
+		{
+		err = iSgImage.GetInfo(info);
+		}
+	
+	if (err == KErrNone)
+		{
+		// Create an EGL target surface.
+		// Get the right Config index for this RSgImage format.
+		pixmapAttribs = TConfigHelper::MatchPixelType(info.iPixelFormat);
+		EGLConfig* currentConfig = aConfigs.Find(pixmapAttribs);
+		GRAPHICS_ASSERT_ALWAYS(currentConfig, EDirectGdiPanicNoConfigFound);	
+			
+		// Set up the surface attribs.
+		const EGLint eglAlphaFormat = (info.iPixelFormat == EUidPixelFormatARGB_8888_PRE) ? EGL_VG_ALPHA_FORMAT_PRE : EGL_VG_ALPHA_FORMAT_NONPRE;
+		EGLint attributeList[] = {EGL_VG_ALPHA_FORMAT, eglAlphaFormat,
+								  EGL_VG_COLORSPACE,   EGL_VG_COLORSPACE_sRGB,
+								  EGL_NONE};
+		
+		// Create an EGL target surface.
+		surface = eglCreatePixmapSurface(display, *currentConfig, (RSgImage*)&iSgImage, attributeList);
+		GRAPHICS_ASSERT_ALWAYS(surface != EGL_NO_SURFACE, EDirectGdiPanicNoDrawingSurface);
+		
+		// See if we have already created a context for this pixel format, create
+		// one if we haven't and save it for reuse later.
+		context = aContexts.Find(pixmapAttribs);	
+		if (context == NULL)
+			{
+			newContext = eglCreateContext(display, *currentConfig, aSharedContext, NULL);	
+			GRAPHICS_ASSERT_ALWAYS(newContext != EGL_NO_CONTEXT, EDirectGdiPanicNoContext);	
+			err = aContexts.Insert(pixmapAttribs, newContext);	
+			if (err == KErrNone)
+				context = &newContext;
+			createdNewContext = ETrue;
+			}
+		}
+	
+	if (err == KErrNone)
+		{
+		err = iDriver.RegisterTargetImage(*this);				
+		}
+	
+	if (err == KErrNone)
+		{
+		// Everything went well.
+		iContext = *context;
+		iSurface = surface;
+		if (createdNewContext)
+			aSharedContext = iContext;
+		Open();
+		}
+	else
+		{
+		// Cleanup.
+		if (surface != EGL_NO_SURFACE)
+			{
+			eglDestroySurface(display, surface);
+			}
+		if (createdNewContext)
+			{
+			if (context)
+				{
+				eglDestroyContext(display, *context);
+				}
+			if (aContexts.Find(pixmapAttribs))
+				{
+				aContexts.Remove(pixmapAttribs);
+				}
+			}
+		}
+	
+	return err;
+	}
+
+/**
+Sets the passed EGLSurface as the current rendering target for EGL, sets the passed 
+EGLContext as the current context. The surface will be used for both read and write 
+operations. The previously current context will be flushed at this point.
+
+@pre The target has been successfully constructed.
+
+@return ETrue if activation was successful, otherwise EFalse.
+*/
+TBool CDirectGdiImageTargetImpl::Activate()
+	{
+	return (EGL_TRUE == eglMakeCurrent(iDriver.EglDisplay(), iSurface, iSurface, iContext));
+	}