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('')
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;