os/graphics/graphicsdeviceinterface/directgdiadaptation/hwsrc/directgdiimagetargetimpl.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include "directgdiadapter.h"
    17 #include "directgdiimagetargetimpl.h"
    18 #include "directgdidriverimpl.h"
    19 #include "confighelper.h"
    20 
    21 /**
    22 Constructs a CDirectGdiImageTargetImpl.
    23 @param	aDriver		The driver implementation which created this target.
    24 */
    25 CDirectGdiImageTargetImpl::CDirectGdiImageTargetImpl(CDirectGdiDriverImpl& aDriver) :
    26 	iDriver(aDriver),
    27 	iSurface(EGL_NO_SURFACE),
    28 	iContext(EGL_NO_CONTEXT)
    29 	{
    30 	}
    31 
    32 /** 
    33 Destructor for CDirectGdiImageTargetImpl - Destroys the EGL surface.
    34 It will remove itself from the driver's image target array, before deleting itself.
    35 */
    36 CDirectGdiImageTargetImpl::~CDirectGdiImageTargetImpl()
    37 {	
    38 #ifdef _DEBUG_DIRECTGDI
    39 	GRAPHICS_LOG_DEBUG("Destroying CDirectGdiImageTargetImpl");
    40 #endif
    41 	if (iDriver.IsCurrentTarget(this))
    42 		{
    43 		iDriver.SetCurrentTarget(NULL);
    44 		}
    45 	
    46 	if (iSurface != EGL_NO_SURFACE)
    47 		{
    48 		// If the surface being deleted is current to EGL, it will defer the destruction of the surface 
    49 		// until something else is made current. Destruction would rather be immediate so that the 
    50 		// associated native pixmap can be used again. In that case, the surface is dereferenced by making 
    51 		// something else current.
    52 		if (eglGetCurrentSurface(EGL_DRAW) == iSurface)
    53 			{
    54 			eglMakeCurrent(iDriver.EglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);			
    55 			}
    56 		
    57 		eglDestroySurface(iDriver.EglDisplay(), iSurface);	
    58 		}
    59 	iDriver.UnregisterTargetImage(*this);	
    60 }
    61 
    62 /**
    63 Two-phase construction of a CDirectGdiImageTargetImpl object.
    64 @param aImage On success, holds a pointer to the newly-created image.
    65 @param aDriver The driver to register this image with.
    66 @param aSgImage The RSgImage which this image will be based upon.
    67 @param aContexts A hash map of already-created EGLContext/Config pairs. 
    68 @param aConfigs A hash map of EGLConfig/Attribute pairs.
    69 @param aSharedContext A reference to the current shared context.
    70 @return KErrNone if successful, KErrNoMemory if not enough memory could be allocated, otherwise a return
    71         value from Construct().
    72 */
    73 TInt CDirectGdiImageTargetImpl::New(CDirectGdiImageTargetImpl*& aImage, 
    74 		CDirectGdiDriverImpl& aDriver, 
    75 		const RSgImage& aSgImage, 
    76 		RHashMap<TInt, EGLContext>& aContexts, 
    77 		RHashMap<TInt, EGLConfig>& aConfigs, 
    78 		EGLContext& aSharedContext)
    79 	{
    80 	CDirectGdiImageTargetImpl* image = new CDirectGdiImageTargetImpl(aDriver);
    81 	if (!image)
    82 		return KErrNoMemory;
    83 	TInt err = image->Construct(aSgImage, aContexts, aConfigs, aSharedContext);
    84 	if (err == KErrNone)
    85 		aImage = image;
    86 	else 
    87 		delete image;
    88 	return err;
    89 	}
    90 
    91 /**
    92 Gets the supplied image structure and sets the internal data. It creates a new image target by creating 
    93 an EGL context corresponding to a pixel type and an EGL config (if the EGLContext is not already created). 
    94 If it was already there, it fetches the EGL context from the hash map. Creates an EGL surface that is then 
    95 set for use by the new target object. Targets that are successfully created are added to an array of targets 
    96 so that they can be closed and deleted correctly at a later stage.
    97 
    98 @param aSgImage The RSgImage to create the source image from.
    99 @param aContexts A hash map of already-created EGLContext/Config pairs. 
   100 @param aConfigs A hash map of EGLConfig/Attribute pairs.
   101 @param aSharedContext A reference to the current shared context.
   102 @return KErrNone if successful, otherwise an error from CDirectGdiImageRef::Construct().
   103 
   104 @panic DGDIAdapter 41, if a matching EGL config is not found for this RSgImage.
   105 @panic DGDIAdapter 42, if an EGLSurface cannot be created.
   106 @panic DGDIAdapter 43, if an EGLContext cannot be created.
   107 */ 
   108 TInt CDirectGdiImageTargetImpl::Construct(const RSgImage& aSgImage, RHashMap<TInt, EGLContext>& aContexts, RHashMap<TInt, EGLConfig>& aConfigs, EGLContext& aSharedContext)
   109 	{
   110 	TSgImageInfo info;
   111 	EGLSurface surface = EGL_NO_SURFACE;
   112 	EGLContext* context = NULL;
   113 	EGLContext newContext = EGL_NO_CONTEXT;
   114 	TBool createdNewContext = EFalse;
   115 	TInt pixmapAttribs = 0;
   116 	const EGLDisplay display = iDriver.EglDisplay();
   117 	
   118 	TInt err = CDirectGdiImageRef::Construct(aSgImage);
   119 			
   120 	if (err == KErrNone)
   121 		{
   122 		err = iSgImage.GetInfo(info);
   123 		}
   124 	
   125 	if (err == KErrNone)
   126 		{
   127 		// Create an EGL target surface.
   128 		// Get the right Config index for this RSgImage format.
   129 		pixmapAttribs = TConfigHelper::MatchPixelType(info.iPixelFormat);
   130 		EGLConfig* currentConfig = aConfigs.Find(pixmapAttribs);
   131 		GRAPHICS_ASSERT_ALWAYS(currentConfig, EDirectGdiPanicNoConfigFound);	
   132 			
   133 		// Set up the surface attribs.
   134 		const EGLint eglAlphaFormat = (info.iPixelFormat == EUidPixelFormatARGB_8888_PRE) ? EGL_VG_ALPHA_FORMAT_PRE : EGL_VG_ALPHA_FORMAT_NONPRE;
   135 		EGLint attributeList[] = {EGL_VG_ALPHA_FORMAT, eglAlphaFormat,
   136 								  EGL_VG_COLORSPACE,   EGL_VG_COLORSPACE_sRGB,
   137 								  EGL_NONE};
   138 		
   139 		// Create an EGL target surface.
   140 		surface = eglCreatePixmapSurface(display, *currentConfig, (RSgImage*)&iSgImage, attributeList);
   141 		GRAPHICS_ASSERT_ALWAYS(surface != EGL_NO_SURFACE, EDirectGdiPanicNoDrawingSurface);
   142 		
   143 		// See if we have already created a context for this pixel format, create
   144 		// one if we haven't and save it for reuse later.
   145 		context = aContexts.Find(pixmapAttribs);	
   146 		if (context == NULL)
   147 			{
   148 			newContext = eglCreateContext(display, *currentConfig, aSharedContext, NULL);	
   149 			GRAPHICS_ASSERT_ALWAYS(newContext != EGL_NO_CONTEXT, EDirectGdiPanicNoContext);	
   150 			err = aContexts.Insert(pixmapAttribs, newContext);	
   151 			if (err == KErrNone)
   152 				context = &newContext;
   153 			createdNewContext = ETrue;
   154 			}
   155 		}
   156 	
   157 	if (err == KErrNone)
   158 		{
   159 		err = iDriver.RegisterTargetImage(*this);				
   160 		}
   161 	
   162 	if (err == KErrNone)
   163 		{
   164 		// Everything went well.
   165 		iContext = *context;
   166 		iSurface = surface;
   167 		if (createdNewContext)
   168 			aSharedContext = iContext;
   169 		Open();
   170 		}
   171 	else
   172 		{
   173 		// Cleanup.
   174 		if (surface != EGL_NO_SURFACE)
   175 			{
   176 			eglDestroySurface(display, surface);
   177 			}
   178 		if (createdNewContext)
   179 			{
   180 			if (context)
   181 				{
   182 				eglDestroyContext(display, *context);
   183 				}
   184 			if (aContexts.Find(pixmapAttribs))
   185 				{
   186 				aContexts.Remove(pixmapAttribs);
   187 				}
   188 			}
   189 		}
   190 	
   191 	return err;
   192 	}
   193 
   194 /**
   195 Sets the passed EGLSurface as the current rendering target for EGL, sets the passed 
   196 EGLContext as the current context. The surface will be used for both read and write 
   197 operations. The previously current context will be flushed at this point.
   198 
   199 @pre The target has been successfully constructed.
   200 
   201 @return ETrue if activation was successful, otherwise EFalse.
   202 */
   203 TBool CDirectGdiImageTargetImpl::Activate()
   204 	{
   205 	return (EGL_TRUE == eglMakeCurrent(iDriver.EglDisplay(), iSurface, iSurface, iContext));
   206 	}