Bug 659832 - Make WebGL working on Maemo r=joe

This commit is contained in:
Oleg Romashin 2011-06-09 21:18:43 -04:00
Родитель 148539b780
Коммит ea114fe9c9
1 изменённых файлов: 131 добавлений и 88 удалений

Просмотреть файл

@ -194,7 +194,7 @@ EGLConfig
CreateConfig(); CreateConfig();
#ifdef MOZ_X11 #ifdef MOZ_X11
static EGLConfig static EGLConfig
CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig = nsnull); CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig = nsnull, EGLenum aDepth = 0);
#endif #endif
static int static int
@ -609,6 +609,47 @@ class GLContextEGL : public GLContext
{ {
friend class TextureImageEGL; friend class TextureImageEGL;
static already_AddRefed<GLContextEGL>
CreateGLContext(const ContextFormat& format,
EGLSurface surface,
EGLConfig config,
GLContextEGL *shareContext,
PRBool aIsOffscreen = PR_FALSE)
{
EGLContext context;
static EGLint cxattribs[] = {
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
LOCAL_EGL_NONE
};
context = sEGLLibrary.fCreateContext(EGL_DISPLAY(),
config,
shareContext ? shareContext->mContext : EGL_NO_CONTEXT,
cxattribs);
if (!context) {
if (shareContext) {
shareContext = nsnull;
context = sEGLLibrary.fCreateContext(EGL_DISPLAY(),
config,
EGL_NO_CONTEXT,
cxattribs);
if (!context) {
NS_WARNING("Failed to create EGLContext!");
return nsnull;
}
}
}
nsRefPtr<GLContextEGL> glContext =
new GLContextEGL(format, shareContext, config,
surface, context, aIsOffscreen);
if (!glContext->Init())
return nsnull;
return glContext.forget();
}
public: public:
GLContextEGL(const ContextFormat& aFormat, GLContextEGL(const ContextFormat& aFormat,
GLContext *aShareContext, GLContext *aShareContext,
@ -813,7 +854,8 @@ public:
static already_AddRefed<GLContextEGL> static already_AddRefed<GLContextEGL>
CreateEGLPixmapOffscreenContext(const gfxIntSize& aSize, CreateEGLPixmapOffscreenContext(const gfxIntSize& aSize,
const ContextFormat& aFormat); const ContextFormat& aFormat,
PRBool aShare);
static already_AddRefed<GLContextEGL> static already_AddRefed<GLContextEGL>
CreateEGLPBufferOffscreenContext(const gfxIntSize& aSize, CreateEGLPBufferOffscreenContext(const gfxIntSize& aSize,
@ -982,6 +1024,42 @@ GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize)
return PR_TRUE; return PR_TRUE;
} }
#ifdef MOZ_X11
if (gUseBackingSurface && mThebesSurface) {
if (aNewSize == mThebesSurface->GetSize()) {
return PR_TRUE;
}
EGLNativePixmapType pixmap = 0;
nsRefPtr<gfxXlibSurface> xsurface =
gfxXlibSurface::Create(DefaultScreenOfDisplay(DefaultXDisplay()),
gfxXlibSurface::FindRenderFormat(DefaultXDisplay(),
gfxASurface::ImageFormatRGB24),
aNewSize);
// Make sure that pixmap created and ready for GL rendering
XSync(DefaultXDisplay(), False);
if (xsurface->CairoStatus() != 0) {
return PR_FALSE;
}
pixmap = xsurface->XDrawable();
if (!pixmap) {
return PR_FALSE;
}
EGLSurface surface;
EGLConfig config = 0;
int depth = gfxUtils::ImageFormatToDepth(gfxPlatform::GetPlatform()->GetOffscreenFormat());
surface = CreateEGLSurfaceForXSurface(xsurface, &config, depth);
if (!config) {
return PR_FALSE;
}
mThebesSurface = xsurface;
return PR_TRUE;
}
#endif
return ResizeOffscreenFBO(aNewSize); return ResizeOffscreenFBO(aNewSize);
} }
@ -1572,7 +1650,9 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget)
new GLContextEGL(ContextFormat(DepthToGLFormat(viewport->depth())), new GLContextEGL(ContextFormat(DepthToGLFormat(viewport->depth())),
NULL, NULL,
NULL, NULL, NULL, NULL,
sEGLLibrary.fGetCurrentContext()); sEGLLibrary.fGetCurrentContext(),
PR_FALSE);
if (!glContext->Init()) if (!glContext->Init())
return nsnull; return nsnull;
@ -1717,37 +1797,19 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget)
return nsnull; return nsnull;
} }
EGLint cxattribs[] = {
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
LOCAL_EGL_NONE
};
GLContextEGL *shareContext = GetGlobalContextEGL(); GLContextEGL *shareContext = GetGlobalContextEGL();
TRY_AGAIN_NO_SHARING: nsRefPtr<GLContextEGL> glContext =
context = sEGLLibrary.fCreateContext(EGL_DISPLAY(), GLContextEGL::CreateGLContext(ContextFormat(ContextFormat::BasicRGB24),
config, surface,
shareContext ? shareContext->mContext : EGL_NO_CONTEXT, config,
cxattribs); shareContext,
if (!context) { PR_FALSE);
if (shareContext) {
NS_WARNING("CreateForWindow -- couldn't share, trying again");
shareContext = nsnull;
goto TRY_AGAIN_NO_SHARING;
}
NS_WARNING("CreateForWindow -- no context, giving up"); if (!glContext) {
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
return nsnull; return nsnull;
} }
nsRefPtr<GLContextEGL> glContext = new GLContextEGL(ContextFormat(ContextFormat::BasicRGB24),
shareContext,
config, surface, context);
if (!glContext->Init())
return nsnull;
#if defined(XP_WIN) || defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO) #if defined(XP_WIN) || defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO)
glContext->SetIsDoubleBuffered(PR_TRUE); glContext->SetIsDoubleBuffered(PR_TRUE);
#endif #endif
@ -1909,7 +1971,7 @@ TRY_ATTRIBS_AGAIN:
#ifdef MOZ_X11 #ifdef MOZ_X11
EGLSurface EGLSurface
CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig) CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig, EGLenum aDepth)
{ {
gfxXlibSurface* xsurface = static_cast<gfxXlibSurface*>(aSurface); gfxXlibSurface* xsurface = static_cast<gfxXlibSurface*>(aSurface);
PRBool opaque = PRBool opaque =
@ -1948,7 +2010,7 @@ CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig)
static EGLint pixmap_config[] = { static EGLint pixmap_config[] = {
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PIXMAP_BIT, LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PIXMAP_BIT,
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT, LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
LOCAL_EGL_DEPTH_SIZE, 0, LOCAL_EGL_DEPTH_SIZE, aDepth,
LOCAL_EGL_BIND_TO_TEXTURE_RGB, LOCAL_EGL_TRUE, LOCAL_EGL_BIND_TO_TEXTURE_RGB, LOCAL_EGL_TRUE,
LOCAL_EGL_NONE LOCAL_EGL_NONE
}; };
@ -1956,7 +2018,7 @@ CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig)
static EGLint pixmap_lock_config[] = { static EGLint pixmap_lock_config[] = {
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PIXMAP_BIT | LOCAL_EGL_LOCK_SURFACE_BIT_KHR, LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PIXMAP_BIT | LOCAL_EGL_LOCK_SURFACE_BIT_KHR,
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT, LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
LOCAL_EGL_DEPTH_SIZE, 0, LOCAL_EGL_DEPTH_SIZE, aDepth,
LOCAL_EGL_BIND_TO_TEXTURE_RGB, LOCAL_EGL_TRUE, LOCAL_EGL_BIND_TO_TEXTURE_RGB, LOCAL_EGL_TRUE,
LOCAL_EGL_NONE LOCAL_EGL_NONE
}; };
@ -1998,18 +2060,9 @@ CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig)
already_AddRefed<GLContextEGL> already_AddRefed<GLContextEGL>
GLContextEGL::CreateEGLPixmapOffscreenContext(const gfxIntSize& aSize, GLContextEGL::CreateEGLPixmapOffscreenContext(const gfxIntSize& aSize,
const ContextFormat& aFormat) const ContextFormat& aFormat,
PRBool aShare)
{ {
// XXX -- write me.
// This needs to find a FBConfig/Visual that matches aFormat, and allocate
// a gfxXlibSurface of the appropriat format, and then create a context
// for it.
//
// The code below is almost correct, except it doesn't do the format-FBConfig
// matching, instead just creating a random gfxXlibSurface. The code below just
// uses context sharing and a FBO target, when instead it should avoid context
// sharing if some form of texture-from-pixmap functionality is available.
gfxASurface *thebesSurface = nsnull; gfxASurface *thebesSurface = nsnull;
EGLNativePixmapType pixmap = 0; EGLNativePixmapType pixmap = 0;
@ -2018,7 +2071,7 @@ GLContextEGL::CreateEGLPixmapOffscreenContext(const gfxIntSize& aSize,
gfxXlibSurface::Create(DefaultScreenOfDisplay(DefaultXDisplay()), gfxXlibSurface::Create(DefaultScreenOfDisplay(DefaultXDisplay()),
gfxXlibSurface::FindRenderFormat(DefaultXDisplay(), gfxXlibSurface::FindRenderFormat(DefaultXDisplay(),
gfxASurface::ImageFormatRGB24), gfxASurface::ImageFormatRGB24),
gfxIntSize(16, 16)); gUseBackingSurface ? aSize : gfxIntSize(16, 16));
// XSync required after gfxXlibSurface::Create, otherwise EGL will fail with BadDrawable error // XSync required after gfxXlibSurface::Create, otherwise EGL will fail with BadDrawable error
XSync(DefaultXDisplay(), False); XSync(DefaultXDisplay(), False);
@ -2037,40 +2090,21 @@ GLContextEGL::CreateEGLPixmapOffscreenContext(const gfxIntSize& aSize,
EGLConfig config = 0; EGLConfig config = 0;
#ifdef MOZ_X11 #ifdef MOZ_X11
surface = CreateEGLSurfaceForXSurface(thebesSurface, &config); int depth = gfxUtils::ImageFormatToDepth(gfxPlatform::GetPlatform()->GetOffscreenFormat());
surface = CreateEGLSurfaceForXSurface(thebesSurface, &config, gUseBackingSurface ? depth : 0);
#endif #endif
if (!config) { if (!config) {
return nsnull; return nsnull;
} }
EGLint cxattribs[] = { GLContextEGL *shareContext = aShare ? GetGlobalContextEGL() : nsnull;
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
LOCAL_EGL_NONE
};
GLContextEGL *shareContext = GetGlobalContextEGL(); nsRefPtr<GLContextEGL> glContext =
if (!shareContext) { GLContextEGL::CreateGLContext(aFormat,
// we depend on context sharing currently surface,
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface); config,
return nsnull; shareContext,
} PR_TRUE);
EGLContext context = sEGLLibrary.fCreateContext(EGL_DISPLAY(),
config,
shareContext->Context(),
cxattribs);
if (!context) {
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
return nsnull;
}
nsRefPtr<GLContextEGL> glContext = new GLContextEGL(aFormat, shareContext,
config, surface, context,
PR_TRUE);
if (!glContext->Init() ||
!glContext->ResizeOffscreenFBO(aSize))
return nsnull;
glContext->HoldSurface(thebesSurface); glContext->HoldSurface(thebesSurface);
@ -2092,7 +2126,23 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
#if defined(ANDROID) || defined(XP_WIN) #if defined(ANDROID) || defined(XP_WIN)
return GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, aFormat); return GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, aFormat);
#elif defined(MOZ_X11) #elif defined(MOZ_X11)
return GLContextEGL::CreateEGLPixmapOffscreenContext(aSize, aFormat); nsRefPtr<GLContextEGL> glContext =
GLContextEGL::CreateEGLPixmapOffscreenContext(aSize, aFormat, PR_TRUE);
if (!glContext) {
return nsnull;
}
if (!glContext->GetSharedContext()) {
// no point in returning anything if sharing failed, we can't
// render from this
return nsnull;
}
if (!gUseBackingSurface && !glContext->ResizeOffscreenFBO(aSize)) {
// we weren't able to create the initial
// offscreen FBO, so this is dead
return nsnull;
}
return glContext.forget();
#else #else
return nsnull; return nsnull;
#endif #endif
@ -2137,23 +2187,13 @@ GLContextProviderEGL::CreateForNativePixmapSurface(gfxASurface* aSurface)
return nsnull; return nsnull;
} }
EGLint cxattribs[] = { GLContextEGL *shareContext = GetGlobalContextEGL();
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2, gfxXlibSurface* xsurface = static_cast<gfxXlibSurface*>(aSurface);
LOCAL_EGL_NONE
};
context = sEGLLibrary.fCreateContext(EGL_DISPLAY(),
config,
EGL_NO_SURFACE,
cxattribs);
if (!context) {
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
return nsnull;
}
nsRefPtr<GLContextEGL> glContext = nsRefPtr<GLContextEGL> glContext =
new GLContextEGL(ContextFormat(ContentTypeToGLFormat(aSurface->GetContentType())), GLContextEGL::CreateGLContext(DepthToGLFormat(xsurface->XRenderFormat()->depth),
nsnull, config, surface, context, PR_FALSE); surface, config, shareContext, PR_FALSE);
glContext->HoldSurface(aSurface); glContext->HoldSurface(aSurface);
return glContext.forget().get(); return glContext.forget().get();
@ -2174,7 +2214,10 @@ GLContextProviderEGL::GetGlobalContext()
static bool triedToCreateContext = false; static bool triedToCreateContext = false;
if (!triedToCreateContext && !gGlobalContext) { if (!triedToCreateContext && !gGlobalContext) {
triedToCreateContext = true; triedToCreateContext = true;
gGlobalContext = CreateOffscreen(gfxIntSize(16, 16)); gGlobalContext =
GLContextEGL::CreateEGLPixmapOffscreenContext(gfxIntSize(16, 16),
ContextFormat(ContextFormat::BasicRGB24),
PR_FALSE);
if (gGlobalContext) if (gGlobalContext)
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE); gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
} }