diff --git a/dom/canvas/test/webgl-mochitest.ini b/dom/canvas/test/webgl-mochitest.ini index 3ca441d71641..77c4a7f27fcd 100644 --- a/dom/canvas/test/webgl-mochitest.ini +++ b/dom/canvas/test/webgl-mochitest.ini @@ -3,6 +3,8 @@ support-files = webgl-mochitest/driver-info.js webgl-mochitest/webgl-util.js +[webgl-mochitest/test-backbuffer-channels.html] +[webgl-mochitest/test-hidden-alpha.html] [webgl-mochitest/test_depth_readpixels.html] [webgl-mochitest/test_draw.html] [webgl-mochitest/test_fb_param.html] diff --git a/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py b/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py index 56ac24e37b67..77461162675a 100644 --- a/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py +++ b/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py @@ -9,7 +9,7 @@ extDotPos = mochiPath.find('.html') assert extDotPos != -1, 'mochitest target must be an html doc.' testPath = mochiPath[:extDotPos] + '.solo.html' - + def ReadLocalFile(include): incPath = os.path.dirname(mochiPath) filePath = os.path.join(incPath, include) @@ -31,22 +31,29 @@ def ReadLocalFile(include): kSimpleTestReplacement = '''\n
\n''' -fin = open(mochiPath, 'r') -fout = open(testPath, 'w') +fin = open(mochiPath, 'rb') +fout = open(testPath, 'wb') includePattern = re.compile('\\s*') cssPattern = re.compile(']*)[\'"]>') for line in fin: @@ -54,7 +61,7 @@ for line in fin: for css in cssPattern.findall(line): skipLine = True print('Ignoring stylesheet: ' + css) - + for inc in includePattern.findall(line): skipLine = True if inc == '/MochiKit/MochiKit': @@ -64,7 +71,7 @@ for line in fin: print('Injecting SimpleTest replacement') fout.write(kSimpleTestReplacement); continue - + incData = ReadLocalFile(inc + '.js') if not incData: print('Warning: Unknown JS file ignored: ' + inc + '.js') @@ -78,7 +85,7 @@ for line in fin: if skipLine: continue - + fout.write(line) continue diff --git a/dom/canvas/test/webgl-mochitest/test-backbuffer-channels.html b/dom/canvas/test/webgl-mochitest/test-backbuffer-channels.html new file mode 100644 index 000000000000..28434e6dc0b9 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/test-backbuffer-channels.html @@ -0,0 +1,111 @@ + +WebGL test: bug 958723 + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/test-hidden-alpha.html b/dom/canvas/test/webgl-mochitest/test-hidden-alpha.html new file mode 100644 index 000000000000..3b15993d483f --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/test-hidden-alpha.html @@ -0,0 +1,153 @@ + +WebGL test: Hidden alpha on no-alpha contexts + + + + + + + + + + + diff --git a/gfx/gl/SharedSurfaceANGLE.cpp b/gfx/gl/SharedSurfaceANGLE.cpp index 20ff9f872f6e..355a338427d2 100644 --- a/gfx/gl/SharedSurfaceANGLE.cpp +++ b/gfx/gl/SharedSurfaceANGLE.cpp @@ -11,6 +11,73 @@ namespace mozilla { namespace gl { +// Returns `EGL_NO_SURFACE` (`0`) on error. +static EGLSurface +CreatePBufferSurface(GLLibraryEGL* egl, + EGLDisplay display, + EGLConfig config, + const gfx::IntSize& size) +{ + auto width = size.width; + auto height = size.height; + + EGLint attribs[] = { + LOCAL_EGL_WIDTH, width, + LOCAL_EGL_HEIGHT, height, + LOCAL_EGL_NONE + }; + + DebugOnly preCallErr = egl->fGetError(); + MOZ_ASSERT(preCallErr == LOCAL_EGL_SUCCESS); + EGLSurface surface = egl->fCreatePbufferSurface(display, config, attribs); + EGLint err = egl->fGetError(); + if (err != LOCAL_EGL_SUCCESS) + return 0; + + return surface; +} + +/*static*/ UniquePtr +SharedSurface_ANGLEShareHandle::Create(GLContext* gl, + EGLContext context, EGLConfig config, + const gfx::IntSize& size, bool hasAlpha) +{ + GLLibraryEGL* egl = &sEGLLibrary; + MOZ_ASSERT(egl); + MOZ_ASSERT(egl->IsExtensionSupported( + GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle)); + + if (!context || !config) + return nullptr; + + EGLDisplay display = egl->Display(); + EGLSurface pbuffer = CreatePBufferSurface(egl, display, config, size); + if (!pbuffer) + return nullptr; + + // Declare everything before 'goto's. + HANDLE shareHandle = nullptr; + bool ok = egl->fQuerySurfacePointerANGLE(display, + pbuffer, + LOCAL_EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, + &shareHandle); + if (!ok) { + egl->fDestroySurface(egl->Display(), pbuffer); + return nullptr; + } + + GLuint fence = 0; + if (gl->IsExtensionSupported(GLContext::NV_fence)) { + gl->MakeCurrent(); + gl->fGenFences(1, &fence); + } + + typedef SharedSurface_ANGLEShareHandle ptrT; + UniquePtr ret( new ptrT(gl, egl, size, hasAlpha, context, + pbuffer, shareHandle, fence) ); + return Move(ret); +} + EGLDisplay SharedSurface_ANGLEShareHandle::Display() { @@ -114,6 +181,9 @@ SharedSurface_ANGLEShareHandle::PollSync_ContentThread_Impl() return PollSync(); } +//////////////////////////////////////////////////////////////////////////////// +// Factory + static void FillPBufferAttribs_ByBits(nsTArray& aAttrs, int redBits, int greenBits, @@ -169,15 +239,25 @@ FillPBufferAttribs_BySizes(nsTArray& attribs, alpha = 8; } - FillPBufferAttribs_ByBits(attribs, - red, green, blue, alpha, - depthBits, stencilBits); + FillPBufferAttribs_ByBits(attribs, red, green, blue, alpha, depthBits, + stencilBits); +} + +static bool +DoesAttribBitsMatchCapBool(GLLibraryEGL* egl, EGLConfig config, EGLint attrib, + bool capBool) +{ + EGLint bits = 0; + egl->fGetConfigAttrib(egl->Display(), config, attrib, &bits); + MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS); + + bool hasBits = !!bits; + + return hasBits == capBool; } static EGLConfig -ChooseConfig(GLContext* gl, - GLLibraryEGL* egl, - const SurfaceCaps& caps) +ChooseConfig(GLContext* gl, GLLibraryEGL* egl, const SurfaceCaps& caps) { MOZ_ASSERT(egl); MOZ_ASSERT(caps.color); @@ -188,28 +268,43 @@ ChooseConfig(GLContext* gl, // Ok, now we have everything. nsTArray attribs(32); - FillPBufferAttribs_BySizes(attribs, - caps.bpp16, caps.alpha, - depthBits, stencilBits); + FillPBufferAttribs_BySizes(attribs, caps.bpp16, caps.alpha, depthBits, + stencilBits); // Time to try to get this config: EGLConfig configs[64]; int numConfigs = sizeof(configs)/sizeof(EGLConfig); int foundConfigs = 0; - if (!egl->fChooseConfig(egl->Display(), - attribs.Elements(), - configs, numConfigs, - &foundConfigs) || + if (!egl->fChooseConfig(egl->Display(), attribs.Elements(), configs, + numConfigs, &foundConfigs) || !foundConfigs) { NS_WARNING("No configs found for the requested formats."); return EGL_NO_CONFIG; } - // TODO: Pick a config progamatically instead of hoping that - // the first config will be minimally matching our request. - EGLConfig config = configs[0]; + // The requests passed to ChooseConfig are treated as minimums. If you ask + // for 0 bits of alpha, we might still get 8 bits. + EGLConfig config = EGL_NO_CONFIG; + for (int i = 0; i < foundConfigs; i++) { + EGLConfig cur = configs[0]; + if (DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_ALPHA_SIZE, + caps.alpha) && + DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_DEPTH_SIZE, + caps.depth) && + DoesAttribBitsMatchCapBool(egl, cur, LOCAL_EGL_STENCIL_SIZE, + caps.stencil)) + { + config = cur; + break; + } + } + + if (config == EGL_NO_CONFIG) { + NS_WARNING("No acceptable EGLConfig found."); + return EGL_NO_CONFIG; + } if (gl->DebugMode()) { egl->DumpEGLConfig(config); @@ -218,73 +313,6 @@ ChooseConfig(GLContext* gl, return config; } -// Returns `EGL_NO_SURFACE` (`0`) on error. -static EGLSurface -CreatePBufferSurface(GLLibraryEGL* egl, - EGLDisplay display, - EGLConfig config, - const gfx::IntSize& size) -{ - auto width = size.width; - auto height = size.height; - - EGLint attribs[] = { - LOCAL_EGL_WIDTH, width, - LOCAL_EGL_HEIGHT, height, - LOCAL_EGL_NONE - }; - - DebugOnly preCallErr = egl->fGetError(); - MOZ_ASSERT(preCallErr == LOCAL_EGL_SUCCESS); - EGLSurface surface = egl->fCreatePbufferSurface(display, config, attribs); - EGLint err = egl->fGetError(); - if (err != LOCAL_EGL_SUCCESS) - return 0; - - return surface; -} - -/*static*/ UniquePtr -SharedSurface_ANGLEShareHandle::Create(GLContext* gl, - EGLContext context, EGLConfig config, - const gfx::IntSize& size, bool hasAlpha) -{ - GLLibraryEGL* egl = &sEGLLibrary; - MOZ_ASSERT(egl); - MOZ_ASSERT(egl->IsExtensionSupported( - GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle)); - - if (!context || !config) - return nullptr; - - EGLDisplay display = egl->Display(); - EGLSurface pbuffer = CreatePBufferSurface(egl, display, config, size); - if (!pbuffer) - return nullptr; - - // Declare everything before 'goto's. - HANDLE shareHandle = nullptr; - bool ok = egl->fQuerySurfacePointerANGLE(display, - pbuffer, - LOCAL_EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, - &shareHandle); - if (!ok) { - egl->fDestroySurface(egl->Display(), pbuffer); - return nullptr; - } - - GLuint fence = 0; - if (gl->IsExtensionSupported(GLContext::NV_fence)) { - gl->MakeCurrent(); - gl->fGenFences(1, &fence); - } - - typedef SharedSurface_ANGLEShareHandle ptrT; - UniquePtr ret( new ptrT(gl, egl, size, hasAlpha, context, - pbuffer, shareHandle, fence) ); - return Move(ret); -} - /*static*/ UniquePtr SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, const SurfaceCaps& caps) @@ -295,25 +323,36 @@ SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, auto ext = GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle; if (!egl->IsExtensionSupported(ext)) - { return nullptr; - } + bool success; typedef SurfaceFactory_ANGLEShareHandle ptrT; - UniquePtr ret( new ptrT(gl, egl, caps) ); + UniquePtr ret( new ptrT(gl, egl, caps, &success) ); + + if (!success) + return nullptr; + return Move(ret); } SurfaceFactory_ANGLEShareHandle::SurfaceFactory_ANGLEShareHandle(GLContext* gl, GLLibraryEGL* egl, - const SurfaceCaps& caps) + const SurfaceCaps& caps, + bool* const out_success) : SurfaceFactory(gl, SharedSurfaceType::EGLSurfaceANGLE, caps) , mProdGL(gl) , mEGL(egl) { - mConfig = ChooseConfig(mProdGL, mEGL, mReadCaps); + MOZ_ASSERT(out_success); + *out_success = false; + mContext = GLContextEGL::Cast(mProdGL)->GetEGLContext(); + mConfig = ChooseConfig(mProdGL, mEGL, mReadCaps); + if (mConfig == EGL_NO_CONFIG) + return; + MOZ_ASSERT(mConfig && mContext); + *out_success = true; } } /* namespace gl */ diff --git a/gfx/gl/SharedSurfaceANGLE.h b/gfx/gl/SharedSurfaceANGLE.h index 334d7b6dfecb..d13c7771a605 100644 --- a/gfx/gl/SharedSurfaceANGLE.h +++ b/gfx/gl/SharedSurfaceANGLE.h @@ -88,7 +88,8 @@ public: protected: SurfaceFactory_ANGLEShareHandle(GLContext* gl, GLLibraryEGL* egl, - const SurfaceCaps& caps); + const SurfaceCaps& caps, + bool* const out_success); virtual UniquePtr CreateShared(const gfx::IntSize& size) MOZ_OVERRIDE { bool hasAlpha = mReadCaps.alpha;