b=603367; use ANGLE for WebGL on Win32; r=bjacob
authorVladimir Vukicevic <vladimir@pobox.com>
Fri, 03 Dec 2010 14:44:01 -0800
changeset 58583 f1dd337db722f9ae3c57cd80d50a8ac654037b96
parent 58582 370f95da0cc1959c7ff3df5254d93e3e511cbf39
child 58584 3bb7e1a3cb223816f3a47d3df321f8471e389463
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersbjacob
bugs603367
milestone2.0b8pre
b=603367; use ANGLE for WebGL on Win32; r=bjacob
browser/installer/package-manifest.in
config/autoconf.mk.in
configure.in
content/canvas/src/WebGLContext.cpp
gfx/angle/Makefile.in
gfx/thebes/GLContextProviderEGL.cpp
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -400,16 +400,24 @@
 @BINPATH@/components/nsUrlClassifierLib.js
 @BINPATH@/components/url-classifier.xpt
 
 ; GNOME hooks
 #ifdef MOZ_ENABLE_GNOME_COMPONENT
 @BINPATH@/components/@DLL_PREFIX@mozgnome@DLL_SUFFIX@
 #endif
 
+; ANGLE on Win32
+#ifdef XP_WIN32
+#ifndef HAVE_64BIT_OS
+@BINPATH@/libEGL.dll
+@BINPATH@/libGLESv2.dll
+#endif
+#endif
+
 ; [Browser Chrome Files]
 @BINPATH@/chrome/browser@JAREXT@
 @BINPATH@/chrome/browser.manifest
 @BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf
 @BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/icon.png
 @BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/preview.png
 #if MOZ_UPDATE_CHANNEL == beta
 @BINPATH@/extensions/testpilot@labs.mozilla.com/*
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -172,16 +172,18 @@ VPX_X86_ASM = @VPX_X86_ASM@
 VPX_ARM_ASM = @VPX_ARM_ASM@
 NS_PRINTING = @NS_PRINTING@
 MOZ_PDF_PRINTING = @MOZ_PDF_PRINTING@
 MOZ_CRASHREPORTER = @MOZ_CRASHREPORTER@
 MOZ_HELP_VIEWER = @MOZ_HELP_VIEWER@
 MOC= @MOC@
 MOZ_NSS_PATCH = @MOZ_NSS_PATCH@
 MOZ_WEBGL = @MOZ_WEBGL@
+MOZ_ANGLE = @MOZ_ANGLE@
+MOZ_DIRECTX_SDK_PATH = @MOZ_DIRECTX_SDK_PATH@
 
 MOZ_JAVAXPCOM = @MOZ_JAVAXPCOM@
 JAVA_INCLUDE_PATH="@JAVA_INCLUDE_PATH@"
 JAVA="@JAVA@"
 JAVAC="@JAVAC@"
 JAR="@JAR@"
 
 TAR=@TAR@
--- a/configure.in
+++ b/configure.in
@@ -6310,16 +6310,61 @@ if test -n "${MOZ_JAVAXPCOM}"; then
     esac
     if test ! -f "$JAVA_INCLUDE_PATH/jni.h"; then
       AC_MSG_ERROR([The header jni.h was not found.  Set \$JAVA_HOME to your java sdk directory, use --with-java-bin-path={java-bin-dir}, or reconfigure with --disable-javaxpcom.])
     fi
   fi
 fi
 
 dnl ========================================================
+dnl = ANGLE OpenGL->D3D translator for WebGL
+dnl = * only applies to win32
+dnl = * enabled by default (shipping build); requires explicit --disable to disable
+dnl ========================================================
+MOZ_ANGLE=
+MOZ_DIRECTX_SDK_PATH=
+case "$target_os" in
+    *msvc*|*mks*|*cygwin*|*mingw*)
+        MOZ_ANGLE=1
+        ;;
+esac
+
+if test -n "$MOZ_ANGLE"; then
+MOZ_ARG_DISABLE_BOOL(angle,
+[  --disable-angle     Disable building of ANGLE for WebGL->D3D translation],
+    MOZ_ANGLE=,
+    MOZ_ANGLE=1)
+
+if test -n "$MOZ_ANGLE"; then
+  if test -z "$_WIN32_MSVC"; then
+    AC_MSG_ERROR([Building ANGLE requires MSVC.  To build without ANGLE, reconfigure with --disable-angle.])
+  fi
+
+  AC_CHECK_HEADER(d3dx9.h, [], [MOZ_ANGLE=])
+
+  if test -z "$MOZ_ANGLE"; then
+    # Try again, but try to get the SDK path from the registry.  We're going to hardcode
+    # the February 2010 SDK, since that's the one that's installed on the tinderboxen.
+    MOZ_DIRECTX_SDK_PATH=`reg query 'HKLM\Software\Microsoft\DirectX\Microsoft DirectX SDK (February 2010)' //v InstallPath | grep REG_SZ | sed 's,  *, ,g' | cut -d' ' -f4`
+    if test -n "$MOZ_DIRECTX_SDK_PATH" ; then
+      if test -f "$MOZ_DIRECTX_SDK_PATH"/include/d3dx9.h && test -f "$MOZ_DIRECTX_SDK_PATH"/lib/x86/dxguid.lib ; then
+        AC_MSG_WARN([Found DirectX SDK in registry, using $MOZ_DIRECTX_SDK])
+        MOZ_ANGLE=1
+      fi
+    fi
+  fi
+
+  if test -z "$MOZ_ANGLE"; then
+    AC_MSG_WARN([Couldn't find d3dx9.h in your INCLUDE path, needed for ANGLE.  Please install the February 2010 DirectX SDK, or make another version available in your LIB and INCLUDE path env variables.  To explicitly build without ANGLE, reconfigure with --disable-angle.])
+    AC_MSG_WARN([This will become an error in the future.])
+  fi
+fi
+fi
+
+dnl ========================================================
 dnl = Breakpad crash reporting (on by default on supported platforms)
 dnl ========================================================
 
 case $target in
 i?86-*-mingw*|x86_64-*-mingw*)
   MOZ_CRASHREPORTER=1
   ;;
 i?86-apple-darwin*|powerpc-apple-darwin*|x86_64-apple-darwin*)
@@ -8915,16 +8960,18 @@ AC_SUBST(ENABLE_TESTS)
 AC_SUBST(IBMBIDI)
 AC_SUBST(MOZ_UNIVERSALCHARDET)
 AC_SUBST(ACCESSIBILITY)
 AC_SUBST(MOZ_VIEW_SOURCE)
 AC_SUBST(MOZ_SPELLCHECK)
 AC_SUBST(MOZ_USER_DIR)
 AC_SUBST(MOZ_CRASHREPORTER)
 AC_SUBST(MOZ_UPDATER)
+AC_SUBST(MOZ_ANGLE)
+AC_SUBST(MOZ_DIRECTX_SDK_PATH)
 
 AC_SUBST(ENABLE_STRIP)
 AC_SUBST(PKG_SKIP_STRIP)
 AC_SUBST(USE_ELF_DYNSTR_GC)
 AC_SUBST(INCREMENTAL_LINKER)
 AC_SUBST(MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS)
 AC_SUBST(MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS)
 AC_SUBST(MOZ_COMPONENT_NSPR_LIBS)
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -311,22 +311,24 @@ WebGLContext::SetContextOptions(nsIPrope
     if (!GetBoolFromPropertyBag(aOptions, "premultipliedAlpha", &newOpts.premultipliedAlpha))
         newOpts.premultipliedAlpha = true;
 
     GetBoolFromPropertyBag(aOptions, "antialiasHint", &newOpts.antialiasHint);
 
     // enforce that if stencil is specified, we also give back depth
     newOpts.depth |= newOpts.stencil;
 
+#if 0
     LogMessage("aaHint: %d stencil: %d depth: %d alpha: %d premult: %d\n",
                newOpts.antialiasHint ? 1 : 0,
                newOpts.stencil ? 1 : 0,
                newOpts.depth ? 1 : 0,
                newOpts.alpha ? 1 : 0,
                newOpts.premultipliedAlpha ? 1 : 0);
+#endif
 
     if (mOptionsFrozen && newOpts != mOptions) {
         // Error if the options are already frozen, and the ones that were asked for
         // aren't the same as what they were originally.
         return NS_ERROR_FAILURE;
     }
 
     mOptions = newOpts;
@@ -393,18 +395,24 @@ WebGLContext::SetDimensions(PRInt32 widt
 
     PRBool verbose = PR_FALSE;
     prefService->GetBoolPref("webgl.verbose", &verbose);
     mVerbose = verbose;
 
     // Get some prefs for some preferred/overriden things
     PRBool forceOSMesa = PR_FALSE;
     PRBool preferEGL = PR_FALSE;
+    PRBool preferOpenGL = PR_FALSE;
     prefService->GetBoolPref("webgl.force_osmesa", &forceOSMesa);
     prefService->GetBoolPref("webgl.prefer_egl", &preferEGL);
+    prefService->GetBoolPref("webgl.prefer_gl", &preferOpenGL);
+
+    if (PR_GetEnv("MOZ_WEBGL_PREFER_EGL")) {
+        preferEGL = PR_TRUE;
+    }
 
     // Ask GfxInfo about what we should use
     PRBool useOpenGL = PR_TRUE;
     PRBool useANGLE = PR_TRUE;
 
     nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
     if (gfxInfo) {
         PRInt32 status;
@@ -419,45 +427,36 @@ WebGLContext::SetDimensions(PRInt32 widt
             if (status == nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION ||
                 status == nsIGfxInfo::FEATURE_BLOCKED_DEVICE)
             {
                 useANGLE = PR_FALSE;
             }
         }
     }
 
+    // allow forcing GL and not EGL/ANGLE
+    if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL")) {
+        preferEGL = PR_FALSE;
+        useANGLE = PR_FALSE;
+        useOpenGL = PR_TRUE;
+    }
+
     // if we're forcing osmesa, do it first
     if (forceOSMesa) {
         gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
         if (!gl || !InitAndValidateGL()) {
             LogMessage("OSMesa forced, but creating context failed -- aborting!");
             return NS_ERROR_FAILURE;
         }
         LogMessage("Using software rendering via OSMesa (THIS WILL BE SLOW)");
     }
 
 #ifdef XP_WIN
-    // On Windows, we may have a choice of backends, including straight
-    // OpenGL, D3D through ANGLE via EGL, or straight EGL/GLES2.
-    // We don't differentiate the latter two yet, but we allow for
-    // a env var to try EGL first, instead of last; there's also a pref,
-    // the env var being set overrides the pref
-    if (PR_GetEnv("MOZ_WEBGL_PREFER_EGL")) {
-        preferEGL = PR_TRUE;
-    }
-
-    // force opengl instead of EGL/ANGLE
-    if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL")) {
-        preferEGL = PR_FALSE;
-        useANGLE = PR_FALSE;
-        useOpenGL = PR_TRUE;
-    }
-
-    // if we want EGL, try it first
-    if (!gl && (preferEGL || useANGLE)) {
+    // if we want EGL, try it now
+    if (!gl && (preferEGL || useANGLE) && !preferOpenGL) {
         gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
         if (gl && !InitAndValidateGL()) {
             gl = nsnull;
         }
     }
 
     // if it failed, then try the default provider, whatever that is
     if (!gl && useOpenGL) {
--- a/gfx/angle/Makefile.in
+++ b/gfx/angle/Makefile.in
@@ -127,48 +127,58 @@ endif
 include $(topsrcdir)/config/rules.mk
 
 # We have to filter out -pedantic, because of
 # comma-at-end-of-enumerator list failures.  We can try to get this fixed
 # upstream at some point.
 CXXFLAGS := $(filter-out -pedantic,$(CXXFLAGS))
 CFLAGS := $(filter-out -pedantic,$(CFLAGS))
 
-ifdef _MSC_VER
-# disabled for now, but we should be building it in the future once
-# bug 529938 is fixed
-#BUILD_ANGLE = 1
+ifdef MOZ_ANGLE
+# ANGLE only on Win32 for now, the solution isn't set up
+# for 64-bit yet.
+ifndef HAVE_64BIT_OS
+BUILD_ANGLE = 1
+endif
 endif
 
 ifdef BUILD_ANGLE
 ifdef MOZ_DEBUG
 ANGLE_DIR = Debug
 else
 ANGLE_DIR = Release
 endif
 
+ifdef MOZ_DIRECTX_SDK_PATH
+INCLUDE := $(INCLUDE);$(MOZ_DIRECTX_SDK_PATH)\include
+LIB := $(LIB);$(MOZ_DIRECTX_SDK_PATH)\lib\x86
+endif
+
 ANGLE_DEP_PATTERNS = \
 	src/common/*.cpp src/common/*.h \
 	src/compiler/*.cpp src/compiler/*.h \
 	src/compiler/preprocessor/*.cpp src/compiler/preprocessor/*.h \
 	src/libEGL/*.cpp src/libEGL/*.h \
 	src/libGLESv2/*.cpp src/libGLESv2/*.h \
 	$(NULL)
 
 ANGLE_DEPS = $(filter-out Gen_glslang.cpp Gen_glslang_tab.cpp glslang_tab.h,$(wildcard $(ANGLE_DEP_PATTERNS)))
 
-libs:: angle-build/libGLESv2.dll angle-build/libEGL.dll
-	$(INSTALL) $(IFLAGS2) angle-build/libGLESv2.dll angle-build/libEGL.dll $(DIST)/bin
+libs:: libGLESv2.dll libEGL.dll
+	$(INSTALL) $(IFLAGS2) libGLESv2.dll libEGL.dll $(DIST)/bin
 
-angle-build/libGLESv2.dll angle-build/libEGL.dll: $(GLOBAL_DEPS) $(ANGLE_DEPS)
-	@echo "=== Building ANGLE via devenv.exe ==="
-	@rm -rf angle-build
-	@mkdir angle-build
-	@cp -r $(srcdir)/src $(srcdir)/include angle-build
-	@(cd angle-build/src \
+# we don't want this to attempt to parallel-build these dlls;
+# building one will build both.
+libGLESv2.dll: libEGL.dll
+
+libEGL.dll: $(GLOBAL_DEPS) $(ANGLE_DEPS)
+	@(echo "=== Building ANGLE via devenv.exe ===" \
+	&& rm -rf angle-build && mkdir angle-build \
+	&& cp -r $(srcdir)/src $(srcdir)/include angle-build \
+	&& cd angle-build/src \
 	&& echo "Upgrading solution..." \
 	&& devenv angle.sln //upgrade \
 	&& echo "Building solution, target $(ANGLE_DIR)|Win32..." \
 	&& devenv angle.sln //useenv //build "$(ANGLE_DIR)|Win32" \
 	&& echo "Copying dlls..." \
-	&& cp $(ANGLE_DIR)/*.dll ..)
+	&& cp $(ANGLE_DIR)/*.dll ../..)
 
 endif
--- a/gfx/thebes/GLContextProviderEGL.cpp
+++ b/gfx/thebes/GLContextProviderEGL.cpp
@@ -73,19 +73,19 @@ typedef void *EGLNativeDisplayType;
 typedef void *EGLNativePixmapType;
 typedef void *EGLNativeWindowType;
 
 #define EGL_LIB "/system/lib/libEGL.so"
 #define GLES2_LIB "/system/lib/libGLESv2.so"
 
 #elif defined(XP_WIN)
 
-#include <nsServiceManagerUtils.h>
-#include <nsIPrefBranch.h>
-#include <nsILocalFile.h>
+#include "nsServiceManagerUtils.h"
+#include "nsIPrefBranch.h"
+#include "nsILocalFile.h"
 
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN 1
 #endif
 
 #include <windows.h>
 
 typedef HDC EGLNativeDisplayType;
@@ -277,59 +277,61 @@ public:
 
     PRBool EnsureInitialized()
     {
         if (mInitialized) {
             return PR_TRUE;
         }
 
 #ifdef XP_WIN
-        // ANGLE is an addon currently, so we have to do a bit of work
-        // to find the directory; the addon sets this on startup/shutdown.
+        // Allow for explicitly specifying the location of libEGL.dll and
+        // libGLESv2.dll.
         do {
             nsCOMPtr<nsIPrefBranch> prefs = do_GetService("@mozilla.org/preferences-service;1");
-            nsCOMPtr<nsILocalFile> angleFile, glesv2File;
+            nsCOMPtr<nsILocalFile> eglFile, glesv2File;
             if (!prefs)
                 break;
 
             nsresult rv = prefs->GetComplexValue("gfx.angle.egl.path",
                                                  NS_GET_IID(nsILocalFile),
-                                                 getter_AddRefs(angleFile));
-            if (NS_FAILED(rv) || !angleFile)
+                                                 getter_AddRefs(eglFile));
+            if (NS_FAILED(rv) || !eglFile)
                 break;
 
             nsCAutoString s;
 
             // note that we have to load the libs in this order, because libEGL.dll
-            // depends on libGLESv2.dll, but is not in our search path.
+            // depends on libGLESv2.dll, but is not/may not be in our search path.
             nsCOMPtr<nsIFile> f;
-            angleFile->Clone(getter_AddRefs(f));
+            eglFile->Clone(getter_AddRefs(f));
             glesv2File = do_QueryInterface(f);
             if (!glesv2File)
                 break;
 
             glesv2File->Append(NS_LITERAL_STRING("libGLESv2.dll"));
 
             PRLibrary *glesv2lib = nsnull; // this will be leaked on purpose
             glesv2File->Load(&glesv2lib);
             if (!glesv2lib)
                 break;
 
-            angleFile->Append(NS_LITERAL_STRING("libEGL.dll"));
-            angleFile->Load(&mEGLLibrary);
+            eglFile->Append(NS_LITERAL_STRING("libEGL.dll"));
+            eglFile->Load(&mEGLLibrary);
         } while (false);
 #endif
 
         if (!mEGLLibrary) {
             mEGLLibrary = PR_LoadLibrary(EGL_LIB);
-            if (!mEGLLibrary) {
-                NS_WARNING("Couldn't load EGL LIB.");
-                return PR_FALSE;
-            }
         }
+
+        if (!mEGLLibrary) {
+            NS_WARNING("Couldn't load EGL LIB.");
+            return PR_FALSE;
+        }
+
 #define SYMBOL(name) \
     { (PRFuncPtr*) &f##name, { "egl" #name, NULL } }
 
         LibrarySymbolLoader::SymLoadStruct earlySymbols[] = {
             SYMBOL(GetDisplay),
             SYMBOL(GetCurrentContext),
             SYMBOL(MakeCurrent),
             SYMBOL(DestroyContext),