From f90e8bf405be965b66106b903de30744961a2705 Mon Sep 17 00:00:00 2001 From: Oleg Romashin Date: Wed, 23 Jun 2010 05:24:31 -0400 Subject: [PATCH] Bug 571832 - Provide CreateForNativePixmapSurface API. r=vladimir. --HG-- extra : rebase_source : 0f7214266a6bf449620d6b46fd14bc6978b621ee --- gfx/thebes/public/GLContext.h | 8 + gfx/thebes/public/GLContextProvider.h | 19 +++ gfx/thebes/public/GLDefs.h | 6 + gfx/thebes/src/GLContextProviderCGL.mm | 7 + gfx/thebes/src/GLContextProviderEGL.cpp | 178 ++++++++++++++++++++- gfx/thebes/src/GLContextProviderGLX.cpp | 7 + gfx/thebes/src/GLContextProviderNull.cpp | 6 + gfx/thebes/src/GLContextProviderOSMesa.cpp | 6 + gfx/thebes/src/GLContextProviderWGL.cpp | 7 + 9 files changed, 243 insertions(+), 1 deletion(-) diff --git a/gfx/thebes/public/GLContext.h b/gfx/thebes/public/GLContext.h index c1caca5d306..358dafca772 100644 --- a/gfx/thebes/public/GLContext.h +++ b/gfx/thebes/public/GLContext.h @@ -165,6 +165,14 @@ public: */ virtual PRBool SwapBuffers() { return PR_FALSE; } + /** + * Defines a two-dimensional texture image for context target surface + */ + virtual PRBool BindTexImage() { return PR_FALSE; } + /* + * Releases a color buffer that is being used as a texture + */ + virtual PRBool ReleaseTexImage() { return PR_FALSE; } protected: PRBool mInitialized; diff --git a/gfx/thebes/public/GLContextProvider.h b/gfx/thebes/public/GLContextProvider.h index efd77b49c5b..6257bf0e397 100644 --- a/gfx/thebes/public/GLContextProvider.h +++ b/gfx/thebes/public/GLContextProvider.h @@ -43,6 +43,7 @@ #include "nsAutoPtr.h" class nsIWidget; +class gfxASurface; namespace mozilla { namespace gl { @@ -119,6 +120,15 @@ public: * @return Context to use for this window */ already_AddRefed CreateForWindow(nsIWidget *aWidget); + + /** + * Try to create a GL context from native surface for arbitrary gfxASurface + * If surface not compatible this will return NULL + * + * @param aSurface surface to create a context for + * @return Context to use for this surface + */ + already_AddRefed CreateForNativePixmapSurface(gfxASurface *aSurface); }; /** Same as GLContextProvider but for off-screen Mesa rendering */ @@ -146,6 +156,15 @@ public: * @return Context to use for this window */ static already_AddRefed CreateForWindow(nsIWidget *aWidget); + + /** + * Try to create a GL context from native surface for arbitrary gfxASurface + * If surface not compatible this will return NULL + * + * @param aSurface surface to create a context for + * @return Context to use for this surface + */ + static already_AddRefed CreateForNativePixmapSurface(gfxASurface *aSurface); }; extern GLContextProvider THEBES_API sGLContextProvider; diff --git a/gfx/thebes/public/GLDefs.h b/gfx/thebes/public/GLDefs.h index 35602f70993..35ee5053050 100644 --- a/gfx/thebes/public/GLDefs.h +++ b/gfx/thebes/public/GLDefs.h @@ -3168,6 +3168,12 @@ typedef ptrdiff_t GLintptr; #define LOCAL_EGL_MULTISAMPLE_RESOLVE 0x3099 #define LOCAL_EGL_CONTEXT_CLIENT_TYPE 0x3097 #define LOCAL_EGL_CONTEXT_CLIENT_VERSION 0x3098 +#define LOCAL_EGL_BACK_BUFFER 0x3084 +#define LOCAL_EGL_TEXTURE_RGB 0x305D +#define LOCAL_EGL_TEXTURE_RGBA 0x305E +#define LOCAL_EGL_TEXTURE_2D 0x305F +#define LOCAL_EGL_NATIVE_PIXMAP_KHR 0x30B0 +#define LOCAL_EGL_IMAGE_PRESERVED_KHR 0x30D2 #define LOCAL_EGL_FALSE 0 #define LOCAL_EGL_TRUE 1 diff --git a/gfx/thebes/src/GLContextProviderCGL.mm b/gfx/thebes/src/GLContextProviderCGL.mm index 08b64a57bb8..8736e74c20d 100644 --- a/gfx/thebes/src/GLContextProviderCGL.mm +++ b/gfx/thebes/src/GLContextProviderCGL.mm @@ -40,6 +40,7 @@ #include "OpenGL/OpenGL.h" #include #include +#include "gfxASurface.h" namespace mozilla { namespace gl { @@ -250,5 +251,11 @@ GLContextProvider::CreatePBuffer(const gfxIntSize &aSize, return glContext.forget().get(); } +already_AddRefed +GLContextProvider::CreateForNativePixmapSurface(gfxASurface *aSurface) +{ + return nsnull; +} + } /* namespace gl */ } /* namespace mozilla */ diff --git a/gfx/thebes/src/GLContextProviderEGL.cpp b/gfx/thebes/src/GLContextProviderEGL.cpp index a95a7bddc46..95c4e7cc2d3 100644 --- a/gfx/thebes/src/GLContextProviderEGL.cpp +++ b/gfx/thebes/src/GLContextProviderEGL.cpp @@ -55,6 +55,8 @@ #include #include +#include "gfxASurface.h" +#include "gfxXlibSurface.h" typedef Display *EGLNativeDisplayType; typedef Pixmap EGLNativePixmapType; typedef Window EGLNativeWindowType; @@ -96,6 +98,8 @@ typedef void *EGLDisplay; typedef void *EGLSurface; typedef void *EGLClientBuffer; typedef void *EGLCastToRelevantPtr; +typedef void *EGLImageKHR; +typedef void *GLeglImageOES; #define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) #define EGL_NO_CONTEXT ((EGLContext)0) @@ -104,6 +108,7 @@ typedef void *EGLCastToRelevantPtr; GLContextProvider sGLContextProvider; + static class EGLLibrary { public: @@ -143,6 +148,20 @@ public: pfnWaitNative fWaitNative; typedef EGLCastToRelevantPtr (*pfnGetProcAddress)(const char *procname); pfnGetProcAddress fGetProcAddress; + typedef const GLubyte* (*pfnQueryString)(EGLDisplay, EGLint name); + pfnQueryString fQueryString; + typedef EGLBoolean (*pfnBindTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer); + pfnBindTexImage fBindTexImage; + typedef EGLBoolean (*pfnReleaseTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer); + pfnReleaseTexImage fReleaseTexImage; + typedef EGLImageKHR (*pfnCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); + pfnCreateImageKHR fCreateImageKHR; + typedef EGLBoolean (*pfnDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image); + pfnDestroyImageKHR fDestroyImageKHR; + // This is EGL specific GL ext symbol "glEGLImageTargetTexture2DOES" + // Lets keep it here for now. + typedef void (*pfnImageTargetTexture2DOES)(GLenum target, GLeglImageOES image); + pfnImageTargetTexture2DOES fImageTargetTexture2DOES; PRBool EnsureInitialized() { @@ -178,6 +197,9 @@ public: SYMBOL(GetConfigAttrib), SYMBOL(WaitNative), SYMBOL(GetProcAddress), + SYMBOL(QueryString), + SYMBOL(BindTexImage), + SYMBOL(ReleaseTexImage), { NULL, { NULL } } }; @@ -186,6 +208,20 @@ public: return PR_FALSE; } + LibrarySymbolLoader::SymLoadStruct khrSymbols[] = { + { (PRFuncPtr*) &fCreateImageKHR, { "eglCreateImageKHR", NULL } }, + { (PRFuncPtr*) &fDestroyImageKHR, { "eglDestroyImageKHR", NULL } }, + { (PRFuncPtr*) &fImageTargetTexture2DOES, { "glEGLImageTargetTexture2DOES", NULL } }, + { NULL, { NULL } } + }; + + if (!LibrarySymbolLoader::LoadSymbols(mEGLLibrary, &khrSymbols[0], + (LibrarySymbolLoader::PlatformLookupFunction)fGetProcAddress)) + { + // just means that EGL_image_* isn't supported + fCreateImageKHR = nsnull; + } + mInitialized = PR_TRUE; return PR_TRUE; } @@ -200,10 +236,13 @@ class GLContextEGL : public GLContext public: GLContextEGL(EGLDisplay aDisplay, EGLConfig aConfig, EGLSurface aSurface, EGLContext aContext, - void *aGLWidget = nsnull) + void *aGLWidget = nsnull, + gfxASurface *aASurface = nsnull) : mDisplay(aDisplay), mConfig(aConfig) , mSurface(aSurface), mContext(aContext) , mGLWidget(aGLWidget) + , mASurface(aASurface) + , mBound(PR_FALSE) {} ~GLContextEGL() @@ -229,6 +268,45 @@ public: return InitWithPrefix("gl", PR_TRUE); } + PRBool BindTexImage() + { + if (mBound) + if (!ReleaseTexImage()) + return PR_FALSE; + + if (mSurface) { + EGLBoolean success; + success = sEGLLibrary.fBindTexImage(mDisplay, (EGLSurface)mSurface, + LOCAL_EGL_BACK_BUFFER); + if (success == LOCAL_EGL_FALSE) + return PR_FALSE; + } else + return PR_FALSE; + + mBound = PR_TRUE; + return PR_TRUE; + } + + PRBool ReleaseTexImage() + { + if (!mBound) + return PR_TRUE; + + if (!mDisplay) + return PR_FALSE; + + if (mSurface) { + EGLBoolean success; + success = sEGLLibrary.fReleaseTexImage(mDisplay, (EGLSurface)mSurface, LOCAL_EGL_BACK_BUFFER); + if (success == LOCAL_EGL_FALSE) + return PR_FALSE; + } else + return PR_FALSE; + + mBound = PR_FALSE; + return PR_TRUE; + } + PRBool MakeCurrent() { PRBool succeeded = PR_TRUE; @@ -278,6 +356,8 @@ private: EGLSurface mSurface; EGLContext mContext; void *mGLWidget; + nsRefPtr mASurface; + PRBool mBound; }; already_AddRefed @@ -448,6 +528,102 @@ GLContextProvider::CreatePBuffer(const gfxIntSize &aSize, const ContextFormat &a return glContext.forget().get(); } +already_AddRefed +GLContextProvider::CreateForNativePixmapSurface(gfxASurface *aSurface) +{ + EGLDisplay display = nsnull; + EGLSurface surface = nsnull; + EGLContext context = nsnull; + + if (!sEGLLibrary.EnsureInitialized()) + return nsnull; + +#ifdef MOZ_X11 + if (aSurface->GetType() != gfxASurface::SurfaceTypeXlib) { + // Not implemented + return nsnull; + } + + gfxXlibSurface *xsurface = static_cast(aSurface); + + display = sEGLLibrary.fGetDisplay((EGLNativeDisplayType)xsurface->XDisplay()); + if (!display) + return nsnull; + + if (!sEGLLibrary.fInitialize(display, NULL, NULL)) + return nsnull; + + EGLConfig configs[32]; + int numConfigs = 32; + + EGLint pixmap_config[] = { + LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PIXMAP_BIT, + LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT, + LOCAL_EGL_DEPTH_SIZE, 0, + LOCAL_EGL_BIND_TO_TEXTURE_RGB, LOCAL_EGL_TRUE, + LOCAL_EGL_NONE + }; + + EGLint pixmap_config_rgb[] = { + LOCAL_EGL_TEXTURE_TARGET, LOCAL_EGL_TEXTURE_2D, + LOCAL_EGL_TEXTURE_FORMAT, LOCAL_EGL_TEXTURE_RGB, + LOCAL_EGL_NONE + }; + + EGLint pixmap_config_rgba[] = { + LOCAL_EGL_TEXTURE_TARGET, LOCAL_EGL_TEXTURE_2D, + LOCAL_EGL_TEXTURE_FORMAT, LOCAL_EGL_TEXTURE_RGBA, + LOCAL_EGL_NONE + }; + + if (!sEGLLibrary.fChooseConfig(display, pixmap_config, + configs, numConfigs, &numConfigs)) + return nsnull; + + if (numConfigs == 0) + return nsnull; + + PRBool opaque = + aSurface->GetContentType() == gfxASurface::CONTENT_COLOR; + int i = 0; + for (i = 0; i < numConfigs; ++i) { + if (opaque) + surface = sEGLLibrary.fCreatePixmapSurface(display, configs[i], + xsurface->XDrawable(), + pixmap_config_rgb); + else + surface = sEGLLibrary.fCreatePixmapSurface(display, configs[i], + xsurface->XDrawable(), + pixmap_config_rgba); + + if (surface != EGL_NO_SURFACE) + break; + } + + + if (aCreateContext) { + EGLint cxattribs[] = { + LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2, + LOCAL_EGL_NONE + }; + + context = sEGLLibrary.fCreateContext(display, configs[i], 0, cxattribs); + if (!context) { + sEGLLibrary.fDestroySurface(display, surface); + return nsnull; + } + } + + nsRefPtr glContext = + new GLContextEGL(display, configs[i], surface, context, NULL, aSurface); + + return glContext.forget().get(); +#else + // Not implemented + return nsnull; +#endif +} + } /* namespace gl */ } /* namespace mozilla */ diff --git a/gfx/thebes/src/GLContextProviderGLX.cpp b/gfx/thebes/src/GLContextProviderGLX.cpp index 6e07290c292..6d3e13c6ed3 100644 --- a/gfx/thebes/src/GLContextProviderGLX.cpp +++ b/gfx/thebes/src/GLContextProviderGLX.cpp @@ -55,6 +55,7 @@ #include "nsDebug.h" #include "nsIWidget.h" #include "GLXLibrary.h" +#include "gfxASurface.h" namespace mozilla { namespace gl { @@ -431,5 +432,11 @@ GLContextProvider::CreatePBuffer(const gfxIntSize &aSize, const ContextFormat& a return glContext.forget().get(); } +already_AddRefed +GLContextProvider::CreateForNativePixmapSurface(gfxASurface *aSurface) +{ + return nsnull; +} + } /* namespace gl */ } /* namespace mozilla */ diff --git a/gfx/thebes/src/GLContextProviderNull.cpp b/gfx/thebes/src/GLContextProviderNull.cpp index 893a845f423..c73b7699303 100644 --- a/gfx/thebes/src/GLContextProviderNull.cpp +++ b/gfx/thebes/src/GLContextProviderNull.cpp @@ -46,6 +46,12 @@ GLContextProvider::CreateForWindow(nsIWidget*) return nsnull; } +already_AddRefed +GLContextProvider::CreateForNativePixmapSurface(gfxASurface *aSurface) +{ + return 0; +} + already_AddRefed GLContextProvider::CreatePBuffer(const gfxIntSize &, const ContextFormat &) { diff --git a/gfx/thebes/src/GLContextProviderOSMesa.cpp b/gfx/thebes/src/GLContextProviderOSMesa.cpp index 30a28e4b5f3..8d256de6b7b 100644 --- a/gfx/thebes/src/GLContextProviderOSMesa.cpp +++ b/gfx/thebes/src/GLContextProviderOSMesa.cpp @@ -251,6 +251,12 @@ GLContextProviderOSMesa::CreateForWindow(nsIWidget *aWidget) return nsnull; } +already_AddRefed +GLContextProviderOSMesa::CreateForNativePixmapSurface(gfxASurface *aSurface) +{ + return 0; +} + already_AddRefed GLContextProviderOSMesa::CreatePBuffer(const gfxIntSize &aSize, const ContextFormat& aFormat) { diff --git a/gfx/thebes/src/GLContextProviderWGL.cpp b/gfx/thebes/src/GLContextProviderWGL.cpp index aacb79c7fbc..e51f11fc3af 100644 --- a/gfx/thebes/src/GLContextProviderWGL.cpp +++ b/gfx/thebes/src/GLContextProviderWGL.cpp @@ -39,6 +39,7 @@ #include "nsDebug.h" #include "nsIWidget.h" #include "WGLLibrary.h" +#include "gfxASurface.h" namespace mozilla { namespace gl { @@ -411,5 +412,11 @@ GLContextProvider::CreatePBuffer(const gfxIntSize& aSize, const ContextFormat& a return glContext.forget().get(); } +already_AddRefed +GLContextProvider::CreateForNativePixmapSurface(gfxASurface *aSurface) +{ + return nsnull; +} + } /* namespace gl */ } /* namespace mozilla */