hostsupport/hostegl/src/EGLExtension.cpp
branchbug235_bringup_0
changeset 53 c2ef9095503a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hostsupport/hostegl/src/EGLExtension.cpp	Wed Oct 06 17:59:01 2010 +0100
@@ -0,0 +1,360 @@
+/* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and /or associated documentation files
+ * (the "Materials "), to deal in the Materials without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Materials,
+ * and to permit persons to whom the Materials are furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
+ * THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description:
+ *
+ */
+
+#include "EGLExtension.h"
+#include "EGLState.h"
+#include "EGLImage.h"
+#include "EGLContext.h"
+#include "EGLDisplay.h"
+#include "eglInternal.h"
+#include "EGLProcess.h"
+#include "EGLThread.h"
+#include "EGLOs.h"
+#include "ImageTarget.h"
+
+#include <string.h>
+
+typedef struct
+	{
+	const char*      extnName;		// procedure or extension name
+	ProcPointer      procAddr;      // address
+	} TExtnInfo;
+
+static const TExtnInfo eglProcedures[] =
+    { // list of EGL extension name strings, followed by any EGLI_NEW function names
+        {"eglCreateImageKHR", (ProcPointer)eglCreateImageKHR},
+        {"eglDestroyImageKHR", (ProcPointer)eglDestroyImageKHR}
+    };
+
+const EGLint KEglProcCount = sizeof(eglProcedures) / sizeof(TExtnInfo); 
+
+CEGLExtension::CEGLExtension()
+    {
+    }
+
+CEGLExtension::~CEGLExtension(void)
+    {
+    }
+
+ProcPointer CEGLExtension::eglGetProcAddress(const char* aProcname)
+    {
+    EGLint nameLength =  strlen(aProcname);
+	if ((nameLength > 3) && !strncmp(aProcname, "egl", 3))
+		{ // EGL extensions - exhaustive search 
+		for (EGLint idx = 0; idx < KEglProcCount; idx++)
+			{
+			if ( strcmp( aProcname, eglProcedures[idx].extnName ) == 0 )
+				return eglProcedures[idx].procAddr;
+			}
+		}	
+	return NULL;
+    }
+
+static EImageTarget mapImageTarget( EGLenum target )
+	{
+	switch(target)
+		{
+		case EGL_GL_TEXTURE_2D_KHR:
+			return IMAGE_TARGET_TEXTURE_2D;
+		case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
+			return IMAGE_TARGET_TEXTURE_CUBE_MAP_POSITIVE_X;
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
+			return IMAGE_TARGET_TEXTURE_CUBE_MAP_NEGATIVE_X;
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
+			return IMAGE_TARGET_TEXTURE_CUBE_MAP_POSITIVE_Y;
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
+			return IMAGE_TARGET_TEXTURE_CUBE_MAP_NEGATIVE_Y;
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
+			return IMAGE_TARGET_TEXTURE_CUBE_MAP_POSITIVE_Z;
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
+			return IMAGE_TARGET_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+		case EGL_GL_RENDERBUFFER_KHR:
+			return IMAGE_TARGET_RENDERBUFFER;
+		default:
+			EGLI_ASSERT(false);
+		}
+
+	// Not reached.
+	return (EImageTarget)-1;
+	}
+
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR( EGLDisplay dpy,
+												  EGLContext ctx,
+												  EGLenum target,
+												  EGLClientBuffer buffer,
+												  const EGLint *attrib_list )
+    {
+    EGLI_ENTER_RET( EGL_NO_IMAGE_KHR );
+
+    CEGLImage *image = NULL;
+    CEGLDisplay *display = NULL;
+    CEGLContext *context = NULL;
+
+    display = state->GetDisplay( dpy );
+    // Check display
+    //<dpy> must be a valid EGLDisplay
+    if( !display )
+       {                   
+       EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_DISPLAY );
+       }
+
+    context = display->GetContext( ctx ); 
+    // Check context
+    //<ctx> must be a valid OpenVG API context on that display
+    if( !context )
+       {                    
+       EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_CONTEXT );
+       }
+    
+    // Display and context ok, continue...
+    switch( target )
+        {
+        case EGL_NATIVE_PIXMAP_KHR:
+            {
+            // Not supported
+            // 1) set error code to EGL_BAD_PARAMETER
+            // 2) release lock
+            // 3) return no image
+            EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_PARAMETER );
+            break;
+            }
+        case EGL_VG_PARENT_IMAGE_KHR:
+            {            
+            // Context must be client context and api must be openVG
+            if( context->ClientContext() && EGL_OPENVG_API == context->ClientApi() )                    
+                {                        
+                EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_CONTEXT );
+                }
+
+            //<buffer>
+            //must be a handle of a VGImage object valid in the specified context, cast
+            //into the type EGLClientBuffer
+            //Furthermore, the specified VGImage
+            //<buffer> must not be a child image
+            if ( !state->VGInterface()->IsRootImage( buffer ) )
+                {
+                EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_ACCESS );
+                }
+            
+            // TODO:
+            /*
+            1) We also need to check that VGImage is not bound 
+            to a Pbuffer surface
+            
+            2) VGimage has not been already used to create EGLImage. 
+            
+            3) VGImage itself is not created from EGLImage.            
+            */
+            //state->VGInterface()-
+            // 1)
+            if( EGL_PBUFFER_BIT == context->Config()->GetAttribute( EGL_SURFACE_TYPE ) )
+                {
+                // If VGImage is bound to a Pbuffer no EGLImage
+                EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_ACCESS );
+                }
+
+            // Descriptor for pixeldata data values
+            SurfaceDescriptor desc; 
+            // data is actual pixeldata
+            void* data = NULL;
+
+            //Any values
+            //specified in <attr_list> are ignored.
+     
+            // GetImageData will allocate memory for data
+            // data must be deleted in CEGLImage destructor
+            state->VGInterface()->GetImageData( buffer, desc, data );
+            if ( !data )
+                {
+                EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_ACCESS );
+                }
+
+            // Create CEGLImage.
+            image = EGLI_NEW CEGLImage( target, buffer, desc, data );
+            
+            // If EGLImage creation fail then return error code.
+            if( !image )
+                {
+                EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_ALLOC );
+                }
+            // Add refcount to VGImage
+            state->VGInterface()->AddRef( buffer );
+            // Add image in array
+            image = display->AddEGLImage( image );
+            break;
+            }   
+
+        case EGL_GL_TEXTURE_2D_KHR:
+		case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
+        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
+            {
+            // From RFP document
+            // EGL_KHR_gl_image (not required for OpenGL ES 1.1) [R12]
+            /*<ctx> must be a valid OpenGL ES API context on that display.*/
+			if( context->ClientContext() && (EGL_OPENGL_ES_API != context->ClientApi() || 2 != context->ClientVersion()) )
+                {                        
+                EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_CONTEXT );
+                }
+
+            
+            // From spec.
+            /*KHR_gl_texture_2D_image requires the presence of an OpenGL ES
+            implementation (1.0 or later and/or 2.0 or later).*/
+            
+            /*Accepted as an attribute in the <attr_list> parameter of
+            eglCreateImageKHR: EGL_GL_TEXTURE_LEVEL_KHR 0x30BC*/
+
+            //EGL_GL_TEXTURE_LEVEL_KHR  
+
+            /*If <target> is EGL_GL_TEXTURE_2D_KHR, 
+            <buffer> must be the name of a nonzero, EGL_GL_TEXTURE_2D target texture object, 
+            cast into the type EGLClientBuffer.  
+
+            <attr_list> should specify the mipmap level
+            which will be used as the EGLImage source (EGL_GL_TEXTURE_LEVEL_KHR); the
+            specified mipmap level must be part of <buffer>.  If not specified, the
+            default value listed in Table bbb will be used, instead.  Additional
+            values specified in <attr_list> are ignored.  The texture must be complete
+            unless the mipmap level to be used is 0, the texture has mipmap level 0
+            specified, and no other mipmap levels are specified. */
+            
+            SurfaceDescriptor surfDesc;
+            EGLint textureLevel = 0;
+            EGLint dataSize;
+
+            if( attrib_list && attrib_list[0] != EGL_NONE )
+	            {
+                  for(int i=0; attrib_list[i] != EGL_NONE ; i+=2)
+                    {
+                    if( attrib_list[i] == EGL_GL_TEXTURE_LEVEL_KHR )
+                        {
+                        textureLevel = attrib_list[i+1];
+                        }
+                    }
+	            }
+
+			EImageTarget textureTarget = mapImageTarget(target);
+
+			IEGLtoGLES2Interface* iFace = (IEGLtoGLES2Interface*)state->GLESInterface(2);
+			EStatus status = iFace->GetTextureInfo( context->ClientContext(), textureTarget, buffer, textureLevel, surfDesc );
+			if ( status != DGLES2_SUCCESS )
+				{
+				switch( status )
+					{
+					case DGLES2_BAD_PARAMETER:
+					case DGLES2_BAD_MATCH:
+						EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_PARAMETER );
+						break;
+
+					default:
+						EGLI_ASSERT(false);
+					}
+                EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_ALLOC );
+                }
+			dataSize = surfDesc.m_stride * surfDesc.m_height;
+			unsigned char* data = new unsigned char [ dataSize ];
+
+            iFace->GetTextureData( context->ClientContext(), textureTarget, buffer, textureLevel, data );
+            
+            // Create CEGLImage.
+            image = EGLI_NEW CEGLImage( target, buffer, surfDesc, data );
+            
+            // If EGLImage creation fail then return error code.
+            if( !image )
+                {
+                EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_ALLOC );
+                }
+            // Add image in array
+            // That array is in display side.
+            image = display->AddEGLImage( image );
+            break;
+            }
+        case EGL_GL_TEXTURE_3D_KHR:
+            {
+            /*<ctx> must be a valid OpenGL ES API context on that display.*/
+			//EGL_BAD_PARAMETER 
+            // NOT SUPPORTED 
+            EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_PARAMETER );
+            }
+        case EGL_GL_RENDERBUFFER_KHR:
+            {
+            //EGL_BAD_PARAMETER 
+            // NOT SUPPORTED 
+            EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_PARAMETER );
+            }
+
+        default:
+            {
+            //EGL_BAD_PARAMETER 
+            EGLI_LEAVE_RET( EGL_NO_IMAGE_KHR, EGL_BAD_PARAMETER );
+            }
+        }
+    EGLI_LEAVE_RET( image, EGL_SUCCESS );
+    }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR( EGLDisplay dpy,
+												  EGLImageKHR image)
+    {
+    // TODO:
+    /* Check display
+       Delete image from display array*/ 
+    EGLI_ENTER_RET( EGL_FALSE );
+
+    CEGLDisplay *display = NULL;
+    CEGLImage *tempImage = NULL;
+
+    display = state->GetDisplay( dpy );
+    // Check display
+    //<dpy> must be a valid EGLDisplay
+    if( !display )
+       {                   
+       EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_DISPLAY );
+       }
+
+    tempImage = display->GetImage( image );
+    if( !tempImage )
+        {
+        EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
+        }
+
+    // Display and image are both ok...
+    // Let siblings know that image is destroyed...
+    // Delete mother of image...
+    // Remove image...
+    //tempImage
+    display->RemoveEGLImage( image );
+
+    return EGL_TRUE;
+    }
+