os/graphics/graphicsdeviceinterface/directgdiadaptation/hwsrc/directgdidriverprocessstate.cpp
Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include "directgdidriverprocessstate.h"
19 const TInt KMaxProcessStateHeapSize = 0x100000;
23 Reports any error that occurs.
24 This is #defined so that we retain correct line information for the debug stream.
26 #define ProcessEglError(err) \
28 const EGLint eglError = eglGetError(); \
29 if (eglError == EGL_BAD_ALLOC) \
31 else if (eglError == EGL_CONTEXT_LOST) \
35 TBuf16<256> _message; \
36 _message.Format(_L16("EGL Error: %x\n"), eglError); \
37 GRAPHICS_LOGD_DEBUG(_message); \
40 Image source data constructor.
41 @param aSgImageId The unique identifier of the RSgImage used to create the EGLImage and VGImage.
42 @param aEglImage The EGLImage created from the RSgImage.
43 @param aVgImage The VGImage created from aEglImage.
44 @panic DGDIAdapter 48, if invalid images are passed in.
46 CImageSourceData::CImageSourceData(const TSgDrawableId& aSgImageId, EGLImageKHR aEglImage, VGImage aVgImage) :
47 iSgImageId(aSgImageId),
51 GRAPHICS_ASSERT_DEBUG(iEglImage != EGL_NO_IMAGE_KHR, EDirectGdiPanicImageSourceDataConstructorError);
52 GRAPHICS_ASSERT_DEBUG(iVgImage != VG_INVALID_HANDLE, EDirectGdiPanicImageSourceDataConstructorError);
56 Image source data destructor.
57 @panic DGDIAdapter 49, if reference count is not zero when this funtion is called.
59 CImageSourceData::~CImageSourceData()
61 GRAPHICS_ASSERT_ALWAYS(iRefCount == 0, EDirectGdiPanicImageSourceDataRefCountError);
64 XDirectGdiDriverProcessState::XDirectGdiDriverProcessState()
66 iCreateMutexErr = iMutex.CreateLocal();
71 Creates a heap to store EGL and VG images. This heap will be shared between threads in
72 the current process. This is necessary as EGL images are shared between threads, and an attempt
73 to create an EGL image from a RSgImage in two different threads would fail if the EGL image was not
74 also shared. Also gets function pointers to image creation and destruction methods in EGL and saves
75 them for use later. Note that Initialize() must be called before you call CreateVgImage() or
78 @pre The client has called MutexCreationStatus() and checked for KErrNone.
80 @param aDisplay The current EGL display handle
82 @return KErrNone if successful, KErrNoMemory if we fail to create the heap, KErrGeneral
83 if we encounter an EGL error, otherwise one of the system-wide error codes.
85 TInt XDirectGdiDriverProcessState::Initialize(EGLDisplay aDisplay)
89 // No need to re-initialize everything if we have already been initialized.
91 if (iLocalHeap == NULL)
93 // Create a heap that will be used to store EGLImages and VGImages that are created
94 // when the driver creates a source image (in CDirectGdiDriverImpl::CreateDrawableSource())
95 iLocalHeap = UserHeap::ChunkHeap(NULL, 0, KMaxProcessStateHeapSize);
96 if (iLocalHeap == NULL)
102 // Check the availability of the required EGL/VG extensions
105 if (!iCheckedExtensionsAvailable)
107 err = CheckAllEglExtensions(aDisplay);
108 iCheckedExtensionsAvailable = ETrue;
110 #ifdef _DEBUG_DIRECTGDI
111 RDebug::Printf("VG_VENDOR: %s\n", vgGetString(VG_VENDOR));
112 RDebug::Printf("VG_RENDERER : %s\n", vgGetString(VG_RENDERER));
113 RDebug::Printf("VG_VERSION : %s\n", vgGetString(VG_VERSION));
118 // Get function pointers for EGLImage creation and destruction and VGImage creation EGL functions.
119 // These need to be refreshed every time this process state is initialised as it cannot be guaranteed
120 // that the function pointers will remain the same after this process state was last closed
121 // (and EGL was terminated).
124 iPfnEglCreateImageKHR = reinterpret_cast<TeglCreateImageKHRTypefPtr>(eglGetProcAddress("eglCreateImageKHR"));
125 if (iPfnEglCreateImageKHR == NULL)
127 ProcessEglError(err);
128 err = KErrNotSupported;
134 iPfnEglDestroyImageKHR = reinterpret_cast<TeglDestroyImageKHRTypefPtr>(eglGetProcAddress("eglDestroyImageKHR"));
135 if (iPfnEglDestroyImageKHR == NULL)
137 ProcessEglError(err);
138 err = KErrNotSupported;
144 iPfnVgCreateImageTargetKHR = reinterpret_cast<TvgCreateEGLImageTargetKHRTypefPtr>(eglGetProcAddress("vgCreateEGLImageTargetKHR"));
145 if (iPfnVgCreateImageTargetKHR == NULL)
147 ProcessEglError(err);
148 err = KErrNotSupported;
157 Destructor, asserts that the instance count is zero, and the count of images stored is zero.
159 @panic DGDIAdapter 50, if the instance count is not zero (debug-only).
160 @panic DGDIAdapter 51, if the image count is not zero (debug-only).
162 XDirectGdiDriverProcessState::~XDirectGdiDriverProcessState()
164 if (iLocalHeap != NULL)
170 GRAPHICS_ASSERT_DEBUG(iDriverInstanceCount == 0, EDirectGdiPanicProcessStateInstanceCountError);
171 GRAPHICS_ASSERT_DEBUG(iImages.Count() == 0, EDirectGdiPanicProcessStateImageCountError);
175 Creates a VGImage from the passed RSgImage. This method first creates a EGLImageKHR from
176 the RSgImage, from which it can create a VGImage. The EGLImageKHR and the VGImage are saved
177 so that they can be shared if a user attempts to create another VGImage from the same RSgImage.
178 If a VGImage has already been created from the passed RSgImage, the existing image is returned
179 instead of a new one being created. This will increment the reference count on that stored image.
181 @param aDisplay The EGL display to associate the image with.
182 @param aVgImageRet A handle to the VGImage created is returned here.
183 @param aSgImage The VGImage will be created from this RSgImage.
185 @pre Initialize() has been called.
187 @return KErrNone if the image is created successfully, KErrGeneral if an EGL error occurs,
188 otherwise one of the system-wide error codes.
190 @panic DGDIAdapter 33, if one of the member EGL function pointers is NULL (debug-only).
191 If this happens it may be that Initialize() has not been called for this process state.
192 @panic DGDIAdapter 36, if aDisplay is EGL_NO_DISPLAY (debug-only).
194 TInt XDirectGdiDriverProcessState::CreateVgImage(EGLDisplay aDisplay, VGImage& aVgImageRet, const RSgImage& aSgImage)
196 VGImage vgImage = VG_INVALID_HANDLE;
198 aVgImageRet = VG_INVALID_HANDLE;
201 // If this image has already been created, just return a handle to the
202 // previously created one.
203 if (ImageExists(aSgImage, vgImage))
205 aVgImageRet = vgImage;
210 // If the function pointers are NULL, Initialize() may not have been called
211 GRAPHICS_ASSERT_DEBUG(iPfnEglCreateImageKHR, EDirectGdiPanicProcessStateNotInitialized);
212 GRAPHICS_ASSERT_DEBUG(iPfnEglDestroyImageKHR, EDirectGdiPanicProcessStateNotInitialized);
213 GRAPHICS_ASSERT_DEBUG(iPfnVgCreateImageTargetKHR, EDirectGdiPanicProcessStateNotInitialized);
214 GRAPHICS_ASSERT_DEBUG(aDisplay != EGL_NO_DISPLAY, EDirectGdiPanicNoDisplay);
216 // Create an EGLImage from the passed RSgImage, then create a VGImage from that and
217 // assign the VGImage to the newly created source. (The EGL image creation functions
218 // have already been retreived at this stage as function pointers using eglGetProcAddress()
219 // in InitialiseEgl())
221 // Pass in the preserved attribute. Without this the existing image data could be trashed.
222 EGLint createImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE,
225 EGLImageKHR eglImage = iPfnEglCreateImageKHR(aDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, reinterpret_cast<EGLClientBuffer>(&aSgImage), createImageAttribs);
226 if (eglImage == EGL_NO_IMAGE_KHR)
228 ProcessEglError(err);
233 vgImage = iPfnVgCreateImageTargetKHR(eglImage);
234 if (vgImage == VG_INVALID_HANDLE)
236 ProcessEglError(err);
242 // Add the image to the array of images on the process heap
243 err = AddImage(aSgImage, eglImage, vgImage);
248 aVgImageRet = vgImage;
253 if (vgImage != VG_INVALID_HANDLE)
255 vgDestroyImage(vgImage);
257 iPfnEglDestroyImageKHR(aDisplay, eglImage);
266 Destroys the passed VGImage. Searches for the image in the image array and
267 decrements its reference count if found. Destroys the image when the reference count
270 @param aDisplay The EGLDisplay the VGImage to be destroyed was created with.
271 @param aVgImage A handle to the VGImage to destroy.
273 @return KErrNone if the image is destroyed successfully, otherwise one of the system-wide
276 @panic DGDIAdapter 33, if the EGL function pointer for destroying a VGImage is NULL (debug-only).
278 TInt XDirectGdiDriverProcessState::DestroyVgImage(EGLDisplay aDisplay, VGImage aVgImage)
280 GRAPHICS_ASSERT_DEBUG(iPfnEglDestroyImageKHR, EDirectGdiPanicProcessStateNotInitialized);
283 TInt err = RemoveImage(aDisplay, aVgImage);
290 Increments the instance count.
292 void XDirectGdiDriverProcessState::OpenDriver()
295 ++iDriverInstanceCount;
300 Decrements the instance count.
301 If this is the last instance of a DirectGDI driver, the associated EGL display is terminated, and
302 there should be no images left in the array as they should all have been destroyed.
304 @param aDriverEglDisplay An EGLDisplay associated with the driver being closed. If this is the last
305 driver being closed, the display is destroyed.
306 @panic DGDIAdapter 51, if the image count is not zero (debug-only).
308 void XDirectGdiDriverProcessState::CloseDriver(EGLDisplay& aDriverEglDisplay)
311 if (--iDriverInstanceCount == 0 && aDriverEglDisplay != EGL_NO_DISPLAY)
313 eglTerminate(aDriverEglDisplay);
314 aDriverEglDisplay = EGL_NO_DISPLAY;
315 // Set the function pointers to NULL as cannot be guaranteed that they will be recreated at the same address
316 // when EGL is next initialised.
317 iPfnEglCreateImageKHR = NULL;
318 iPfnEglDestroyImageKHR = NULL;
319 iPfnVgCreateImageTargetKHR = NULL;
320 GRAPHICS_ASSERT_DEBUG(iImages.Count() == 0, EDirectGdiPanicProcessStateImageCountError);
326 Check that the following EGL extensions are available:
327 EGL_SYMBIAN_PIXMAP_TYPE_RSGIMAGE
329 EGL_SYMBIAN_image_preserved
331 According to the spec, OpenVG extensions cannot be checked until a context has been made current,
332 which has not happened at this point, so currently there is no check for VG_KHR_EGL_image extension.
334 @pre eglInitialize() must have been called for the passed EGLDisplay.
336 @param aDisplay The current EGL display handle.
338 @return KErrNone if all the extensions are available, KErrNotSupported if one or more
339 of the extensions are not supported by the EGL driver.
341 TInt XDirectGdiDriverProcessState::CheckAllEglExtensions(EGLDisplay aDisplay) const
343 _LIT8(KEglRSgImage, "EGL_SYMBIAN_PIXMAP_TYPE_RSGIMAGE");
344 _LIT8(KEglKhrImage, "EGL_KHR_image");
345 _LIT8(KEglImagePreserved, "EGL_SYMBIAN_image_preserved");
347 TInt err = CheckForEglExtension(aDisplay, KEglRSgImage);
351 err = CheckForEglExtension(aDisplay, KEglKhrImage);
356 err = CheckForEglExtension(aDisplay, KEglImagePreserved);
363 Checks whether the passed EGL extension string is available with this EGL driver.
365 @param aDisplay The current EGL display handle.
366 @param aExtensionString The EGL extension string to search for.
368 @return KErrNotSupported is the extension string is not found, KErrNone if it is found successfully.
370 TInt XDirectGdiDriverProcessState::CheckForEglExtension(EGLDisplay aDisplay,
371 const TDesC8& aExtensionString) const
373 const TText8* extensions = reinterpret_cast<const TText8*>(eglQueryString(aDisplay, EGL_EXTENSIONS));
375 TBool found = EFalse;
378 TPtrC8 ext(extensions);
379 if (ext.Find(aExtensionString) != KErrNotFound)
385 return (found) ? KErrNone : KErrNotSupported;
389 Checks to see that the passed RSgImage exists in the image array. Increases
390 the reference count on the image if it is found. The calling method should be holding the mutex
391 iMutex open before calling this method.
393 @param aSgImage The RSgImage to check for.
394 @param aVgImageRet The handle of the VGImage found is returned here.
396 @pre The mutex iMutex is held.
398 @return ETrue if the image was found, EFalse otherwise.
400 @panic DGDIAdapter 52, if the mutex has not been opened before calling this method.
401 This panic only happens when _DEBUG_DIRECTGDI is defined.
403 TBool XDirectGdiDriverProcessState::ImageExists(const RSgImage& aSgImage, VGImage& aVgImageRet)
405 #ifdef _DEBUG_DIRECTGDI
406 GRAPHICS_ASSERT_ALWAYS(iMutex.IsHeld(), EDirectGdiPanicImageMutexError);
408 aVgImageRet = VG_INVALID_HANDLE;
410 CImageSourceData* imageData = FindImage(aSgImage);
413 aVgImageRet = imageData->VgImage();
417 return (aVgImageRet != VG_INVALID_HANDLE);
421 Searches for an image in the array of images using the passed RSgImage id to find it.
422 The calling method should be holding the images mutex iMutex open before calling this method.
424 @param aSgImage The RSgImage to search for.
426 @pre The mutex iMutex is held.
428 @return Pointer to the CImageSourceData object held in the images array for the passed
429 RSgImage if it is found, NULL if the image is not found.
431 @panic DGDIAdapter 52, if the mutex has not been opened before calling this method.
432 This panic only happens when _DEBUG_DIRECTGDI is defined.
434 CImageSourceData* XDirectGdiDriverProcessState::FindImage(const RSgImage& aSgImage)
436 #ifdef _DEBUG_DIRECTGDI
437 GRAPHICS_ASSERT_ALWAYS(iMutex.IsHeld(), EDirectGdiPanicImageMutexError);
439 CImageSourceData* imageDataRet = NULL;
441 for (TInt i = 0; i < iImages.Count() && !imageDataRet; i++)
443 CImageSourceData* imageData = reinterpret_cast<CImageSourceData*>(iImages[i]);
444 if (imageData->SgImageId() == aSgImage.Id())
446 imageDataRet = imageData;
454 Adds an image to the images array by saving its RSgImage id, its EGLImageKHR handle and its VGImage
455 handle. A new CImageSourceData object is created to hold this information. This CImageSourceData object
456 is also used to maintain a reference count on the number of times this image has been shared.
457 The calling method should be holding the images mutex iMutex open before calling this method.
461 @param aSgImage The RSgImage to store, only the RSgImage id will be stored.
462 @param aEglImage The EGLImageKHR to store.
463 @param aVgImage The VGImage to stord.
465 @pre The mutex iMutex is held.
466 @return KErrNone if the details of the passed image are added to the image array successfully, KErrNoMemory
467 if memory allocation fails, otherwise one of the system-wide error codes.
469 @panic DGDIAdapter 52, if the mutex has not been opened before calling this method.
470 This panic only happens when _DEBUG_DIRECTGDI is defined.
472 TInt XDirectGdiDriverProcessState::AddImage(const RSgImage& aSgImage, EGLImageKHR aEglImage, VGImage aVgImage)
474 #ifdef _DEBUG_DIRECTGDI
475 GRAPHICS_ASSERT_ALWAYS(iMutex.IsHeld(), EDirectGdiPanicImageMutexError);
478 RHeap *prevHeap = User::SwitchHeap(iLocalHeap);
480 CImageSourceData* imageData = new CImageSourceData(aSgImage.Id(), aEglImage, aVgImage);
481 if (imageData == NULL)
487 err = iImages.InsertInAddressOrder(imageData);
498 User::SwitchHeap(prevHeap);
503 Removes the passed image from the image array by searching for it using its VGImage handle.
504 If the image is found in the image array, its reference count will be decremented. When the count reaches
505 zero the image will be removed from the image array and destroyed.
509 @param aDisplay The EGL display this image was created with.
510 @param aVgImage The hande to a VGImage to be removed from the image array.
512 @pre The mutex iMutex is held.
514 @return KErrNone if the image is removed from the image array successfully, KErrNotFound if the image
515 cannot be found in the image array, otherwise one of the system-wide error codes.
517 @panic DGDIAdapter 52, if the mutex has not been opened before calling this method.
518 This panic only happens when _DEBUG_DIRECTGDI is defined.
520 TInt XDirectGdiDriverProcessState::RemoveImage(EGLDisplay aDisplay, VGImage aVgImage)
522 #ifdef _DEBUG_DIRECTGDI
523 GRAPHICS_ASSERT_ALWAYS(iMutex.IsHeld(), EDirectGdiPanicImageMutexError);
527 CImageSourceData* removeImage = NULL;
529 for (TInt i = 0; i < iImages.Count() && (index == -1); i++)
531 if (CImageSourceData* imageData = reinterpret_cast<CImageSourceData*>(iImages[i]))
533 if (imageData->VgImage() == aVgImage)
535 // Only remove the image if the reference count is zero
536 if (imageData->Close() == 0)
537 removeImage = imageData;
545 // Clean up the EGL and VG images
546 vgDestroyImage(removeImage->VgImage());
547 iPfnEglDestroyImageKHR(aDisplay, removeImage->EglImage());
549 RHeap *prevHeap = User::SwitchHeap(iLocalHeap);
550 iImages.Remove(index);
551 iImages.GranularCompress();
553 User::SwitchHeap(prevHeap);