mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Merge inbound to m-c.
This commit is contained in:
commit
abbd67c311
@ -29,10 +29,8 @@ libs:: $(FINAL_TARGET)/chrome/pdfjs.manifest $(FINAL_TARGET)/chrome/shumway.mani
|
||||
$(srcdir)/shumway \
|
||||
$(foreach exclude,$(exclude_files), -X $(srcdir)/shumway/$(exclude)) \
|
||||
$(FINAL_TARGET)/chrome
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py \
|
||||
$(FINAL_TARGET)/chrome.manifest "manifest chrome/pdfjs.manifest"
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py \
|
||||
$(FINAL_TARGET)/chrome.manifest "manifest chrome/shumway.manifest"
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "manifest chrome/pdfjs.manifest")
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "manifest chrome/shumway.manifest")
|
||||
|
||||
ifdef MOZ_METRO
|
||||
$(DIST)/bin/metro/chrome/pdfjs.manifest: $(GLOBAL_DEPS)
|
||||
@ -43,6 +41,5 @@ libs:: $(DIST)/bin/metro/chrome/pdfjs.manifest
|
||||
$(srcdir)/pdfjs \
|
||||
$(foreach exclude,$(exclude_files), -X $(srcdir)/pdfjs/$(exclude)) \
|
||||
$(DIST)/bin/metro/chrome
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py \
|
||||
$(DIST)/bin/metro/chrome.manifest "manifest chrome/pdfjs.manifest"
|
||||
$(call py_action,buildlist,$(DIST)/bin/metro/chrome.manifest "manifest chrome/pdfjs.manifest")
|
||||
endif
|
||||
|
@ -4,21 +4,37 @@
|
||||
|
||||
var AlertsHelper = {
|
||||
_listener: null,
|
||||
_cookie: "",
|
||||
|
||||
showAlertNotification: function ah_show(aImageURL, aTitle, aText, aTextClickable, aCookie, aListener) {
|
||||
Services.obs.addObserver(this, "metro_native_toast_clicked", false);
|
||||
if (aListener) {
|
||||
Services.obs.addObserver(this, "metro_native_toast_clicked", false);
|
||||
Services.obs.addObserver(this, "metro_native_toast_dismissed", false);
|
||||
Services.obs.addObserver(this, "metro_native_toast_shown", false);
|
||||
}
|
||||
this._listener = aListener;
|
||||
this._cookie = aCookie;
|
||||
|
||||
Services.metro.showNativeToast(aTitle, aText, aImageURL);
|
||||
Services.metro.showNativeToast(aTitle, aText, aImageURL, aCookie);
|
||||
},
|
||||
|
||||
closeAlert: function ah_close() {
|
||||
if (this._listener) {
|
||||
Services.obs.removeObserver(this, "metro_native_toast_shown");
|
||||
Services.obs.removeObserver(this, "metro_native_toast_clicked");
|
||||
Services.obs.removeObserver(this, "metro_native_toast_dismissed");
|
||||
this._listener = null;
|
||||
}
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "metro_native_toast_clicked":
|
||||
Services.obs.removeObserver(this, "metro_native_toast_clicked");
|
||||
this._listener.observe(null, "alertclickcallback", this._cookie);
|
||||
this._listener.observe(null, "alertclickcallback", aData);
|
||||
break;
|
||||
case "metro_native_toast_shown":
|
||||
this._listener.observe(null, "alertshow", aData);
|
||||
break;
|
||||
case "metro_native_toast_dismissed":
|
||||
this._listener.observe(null, "alertfinished", aData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ AlertsService.prototype = {
|
||||
classID: Components.ID("{fe33c107-82a4-41d6-8c64-5353267e04c9}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAlertsService]),
|
||||
|
||||
showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener, aName) {
|
||||
showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable,
|
||||
aCookie, aAlertListener, aName, aDir, aLang) {
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
try {
|
||||
browser.AlertsHelper.showAlertNotification(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener);
|
||||
@ -33,6 +34,11 @@ AlertsService.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
closeAlert: function(aName) {
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
browser.AlertsHelper.closeAlert();
|
||||
},
|
||||
|
||||
_getChromeWindow: function (aWindow) {
|
||||
let chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
|
@ -9,12 +9,12 @@
|
||||
#undef Elf_Ehdr
|
||||
#undef Elf_Addr
|
||||
|
||||
#if BITS == 32
|
||||
#define Elf_Ehdr Elf32_Ehdr
|
||||
#define Elf_Addr Elf32_Addr
|
||||
#else
|
||||
#if defined(__LP64__)
|
||||
#define Elf_Ehdr Elf64_Ehdr
|
||||
#define Elf_Addr Elf64_Addr
|
||||
#else
|
||||
#define Elf_Ehdr Elf32_Ehdr
|
||||
#define Elf_Addr Elf32_Addr
|
||||
#endif
|
||||
|
||||
extern __attribute__((visibility("hidden"))) void original_init(int argc, char **argv, char **env);
|
||||
|
@ -30,6 +30,5 @@ $(CSRCS): %.c: ../inject.c
|
||||
|
||||
GARBAGE += $(CSRCS)
|
||||
|
||||
DEFINES += -DBITS=$(if $(HAVE_64BIT_OS),64,32)
|
||||
CFLAGS := -O2 -fno-stack-protector $(filter -m% -I%,$(CFLAGS))
|
||||
$(CPU)-noinit.$(OBJ_SUFFIX): DEFINES += -DNOINIT
|
||||
|
@ -14,14 +14,16 @@ import errno
|
||||
import re
|
||||
import logging
|
||||
from time import localtime
|
||||
from optparse import OptionParser
|
||||
from MozZipFile import ZipFile
|
||||
from cStringIO import StringIO
|
||||
from datetime import datetime
|
||||
|
||||
from utils import pushback_iter, lockFile
|
||||
from mozbuild.util import (
|
||||
lock_file,
|
||||
PushbackIter,
|
||||
)
|
||||
|
||||
from Preprocessor import Preprocessor
|
||||
from buildlist import addEntriesToListFile
|
||||
from mozbuild.action.buildlist import addEntriesToListFile
|
||||
if sys.platform == "win32":
|
||||
from ctypes import windll, WinError
|
||||
CreateHardLink = windll.kernel32.CreateHardLinkA
|
||||
@ -174,7 +176,7 @@ class JarMaker(object):
|
||||
'''updateManifest replaces the % in the chrome registration entries
|
||||
with the given chrome base path, and updates the given manifest file.
|
||||
'''
|
||||
lock = lockFile(manifestPath + '.lck')
|
||||
lock = lock_file(manifestPath + '.lck')
|
||||
try:
|
||||
myregister = dict.fromkeys(map(lambda s: s.replace('%', chromebasepath),
|
||||
register.iterkeys()))
|
||||
@ -215,7 +217,7 @@ class JarMaker(object):
|
||||
pp = self.pp.clone()
|
||||
pp.out = StringIO()
|
||||
pp.do_include(infile)
|
||||
lines = pushback_iter(pp.out.getvalue().splitlines())
|
||||
lines = PushbackIter(pp.out.getvalue().splitlines())
|
||||
try:
|
||||
while True:
|
||||
l = lines.next()
|
||||
@ -252,8 +254,8 @@ class JarMaker(object):
|
||||
'''Internal method called by makeJar to actually process a section
|
||||
of a jar.mn file.
|
||||
|
||||
jarfile is the basename of the jarfile or the directory name for
|
||||
flat output, lines is a pushback_iterator of the lines of jar.mn,
|
||||
jarfile is the basename of the jarfile or the directory name for
|
||||
flat output, lines is a PushbackIter of the lines of jar.mn,
|
||||
the remaining options are carried over from makeJar.
|
||||
'''
|
||||
|
||||
|
@ -2,12 +2,12 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import zipfile
|
||||
import time
|
||||
import binascii, struct
|
||||
import zlib
|
||||
import os
|
||||
from utils import lockFile
|
||||
import time
|
||||
import zipfile
|
||||
|
||||
from mozbuild.util import lock_file
|
||||
|
||||
|
||||
class ZipFile(zipfile.ZipFile):
|
||||
""" Class with methods to open, read, write, close, list zip files.
|
||||
@ -19,7 +19,7 @@ class ZipFile(zipfile.ZipFile):
|
||||
lock = False):
|
||||
if lock:
|
||||
assert isinstance(file, basestring)
|
||||
self.lockfile = lockFile(file + '.lck')
|
||||
self.lockfile = lock_file(file + '.lck')
|
||||
else:
|
||||
self.lockfile = None
|
||||
|
||||
|
@ -25,8 +25,8 @@ ifdef IS_COMPONENT
|
||||
$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
|
||||
$(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
|
||||
ifndef NO_COMPONENTS_MANIFEST
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest"
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)"
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest")
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)")
|
||||
endif
|
||||
endif # IS_COMPONENT
|
||||
endif # SHARED_LIBRARY
|
||||
|
@ -57,6 +57,8 @@ xpidl_modules := @xpidl_modules@
|
||||
linked_xpt_files := $(addprefix $(idl_xpt_dir)/,$(addsuffix .xpt,$(xpidl_modules)))
|
||||
depends_files := $(foreach root,$(xpidl_modules),$(idl_deps_dir)/$(root).pp)
|
||||
|
||||
GARBAGE += $(linked_xpt_files) $(depends_files)
|
||||
|
||||
xpidl:: $(linked_xpt_files)
|
||||
|
||||
$(linked_xpt_files): $(process_py) $(call mkdir_deps,$(idl_deps_dir) $(dist_include_dir) $(idl_xpt_dir))
|
||||
|
@ -1314,8 +1314,8 @@ INSTALL_TARGETS += _XPT_NAME
|
||||
|
||||
ifndef NO_INTERFACES_MANIFEST
|
||||
libs:: $(call mkdir_deps,$(FINAL_TARGET)/components)
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPT_NAME)"
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest"
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPT_NAME)")
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest")
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -1351,7 +1351,7 @@ endif
|
||||
EXTRA_MANIFESTS = $(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))
|
||||
ifneq (,$(EXTRA_MANIFESTS))
|
||||
libs:: $(call mkdir_deps,$(FINAL_TARGET))
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest $(patsubst %,"manifest components/%",$(notdir $(EXTRA_MANIFESTS)))
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest $(patsubst %,"manifest components/%",$(notdir $(EXTRA_MANIFESTS))))
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
119
config/utils.py
119
config/utils.py
@ -1,119 +0,0 @@
|
||||
# >>sys.stderr, This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
'''Utility methods to be used by python build infrastructure.
|
||||
'''
|
||||
|
||||
import os
|
||||
import errno
|
||||
import sys
|
||||
import time
|
||||
import stat
|
||||
|
||||
class LockFile(object):
|
||||
'''LockFile is used by the lockFile method to hold the lock.
|
||||
|
||||
This object should not be used directly, but only through
|
||||
the lockFile method below.
|
||||
'''
|
||||
def __init__(self, lockfile):
|
||||
self.lockfile = lockfile
|
||||
def __del__(self):
|
||||
while True:
|
||||
try:
|
||||
os.remove(self.lockfile)
|
||||
break
|
||||
except OSError as e:
|
||||
if e.errno == errno.EACCES:
|
||||
# another process probably has the file open, we'll retry.
|
||||
# just a short sleep since we want to drop the lock ASAP
|
||||
# (but we need to let some other process close the file first)
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
# re-raise unknown errors
|
||||
raise
|
||||
|
||||
def lockFile(lockfile, max_wait = 600):
|
||||
'''Create and hold a lockfile of the given name, with the given timeout.
|
||||
|
||||
To release the lock, delete the returned object.
|
||||
'''
|
||||
while True:
|
||||
try:
|
||||
fd = os.open(lockfile, os.O_EXCL | os.O_RDWR | os.O_CREAT)
|
||||
# we created the lockfile, so we're the owner
|
||||
break
|
||||
except OSError as e:
|
||||
if (e.errno == errno.EEXIST or
|
||||
(sys.platform == "win32" and e.errno == errno.EACCES)):
|
||||
pass
|
||||
else:
|
||||
# should not occur
|
||||
raise
|
||||
|
||||
try:
|
||||
# the lock file exists, try to stat it to get its age
|
||||
# and read its contents to report the owner PID
|
||||
f = open(lockfile, "r")
|
||||
s = os.stat(lockfile)
|
||||
except EnvironmentError as e:
|
||||
if e.errno == errno.ENOENT or e.errno == errno.EACCES:
|
||||
# we didn't create the lockfile, so it did exist, but it's
|
||||
# gone now. Just try again
|
||||
continue
|
||||
sys.exit("{0} exists but stat() failed: {1}"
|
||||
.format(lockfile, e.strerror))
|
||||
|
||||
# we didn't create the lockfile and it's still there, check
|
||||
# its age
|
||||
now = int(time.time())
|
||||
if now - s[stat.ST_MTIME] > max_wait:
|
||||
pid = f.readline().rstrip()
|
||||
sys.exit("{0} has been locked for more than "
|
||||
"{1} seconds (PID {2})".format(lockfile, max_wait, pid))
|
||||
|
||||
# it's not been locked too long, wait a while and retry
|
||||
f.close()
|
||||
time.sleep(1)
|
||||
|
||||
# if we get here. we have the lockfile. Convert the os.open file
|
||||
# descriptor into a Python file object and record our PID in it
|
||||
|
||||
f = os.fdopen(fd, "w")
|
||||
f.write("{0}\n".format(os.getpid()))
|
||||
f.close()
|
||||
return LockFile(lockfile)
|
||||
|
||||
class pushback_iter(object):
|
||||
'''Utility iterator that can deal with pushed back elements.
|
||||
|
||||
This behaves like a regular iterable, just that you can call
|
||||
iter.pushback(item)
|
||||
to get the given item as next item in the iteration.
|
||||
'''
|
||||
def __init__(self, iterable):
|
||||
self.it = iter(iterable)
|
||||
self.pushed_back = []
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __nonzero__(self):
|
||||
if self.pushed_back:
|
||||
return True
|
||||
|
||||
try:
|
||||
self.pushed_back.insert(0, self.it.next())
|
||||
except StopIteration:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def next(self):
|
||||
if self.pushed_back:
|
||||
return self.pushed_back.pop()
|
||||
return self.it.next()
|
||||
|
||||
def pushback(self, item):
|
||||
self.pushed_back.append(item)
|
114
configure.in
114
configure.in
@ -2498,83 +2498,8 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
dnl Check for int64, uint, and uint_t.
|
||||
dnl ========================================================
|
||||
AC_MSG_CHECKING(for int64)
|
||||
AC_CACHE_VAL(ac_cv_int64,
|
||||
[AC_TRY_COMPILE([#include <stdio.h>
|
||||
#include <sys/types.h>],
|
||||
[int64 foo = 0;],
|
||||
[ac_cv_int64=true],
|
||||
[ac_cv_int64=false])])
|
||||
if test "$ac_cv_int64" = true ; then
|
||||
AC_DEFINE(HAVE_INT64)
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AC_MSG_CHECKING(for uint)
|
||||
AC_CACHE_VAL(ac_cv_uint,
|
||||
[AC_TRY_COMPILE([#include <stdio.h>
|
||||
#include <sys/types.h>],
|
||||
[uint foo = 0;],
|
||||
[ac_cv_uint=true],
|
||||
[ac_cv_uint=false])])
|
||||
if test "$ac_cv_uint" = true ; then
|
||||
AC_DEFINE(HAVE_UINT)
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AC_MSG_CHECKING(for uint_t)
|
||||
AC_CACHE_VAL(ac_cv_uint_t,
|
||||
[AC_TRY_COMPILE([#include <stdio.h>
|
||||
#include <sys/types.h>],
|
||||
[uint_t foo = 0;],
|
||||
[ac_cv_uint_t=true],
|
||||
[ac_cv_uint_t=false])])
|
||||
if test "$ac_cv_uint_t" = true ; then
|
||||
AC_DEFINE(HAVE_UINT_T)
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
dnl On the gcc trunk (as of 2001-02-09) _GNU_SOURCE, and thus __USE_GNU,
|
||||
dnl are defined when compiling C++ but not C. Since the result of this
|
||||
dnl test is used only in C++, do it in C++.
|
||||
AC_LANG_CPLUSPLUS
|
||||
|
||||
AC_MSG_CHECKING(for uname.domainname)
|
||||
AC_CACHE_VAL(ac_cv_have_uname_domainname_field,
|
||||
[AC_TRY_COMPILE([#include <sys/utsname.h>],
|
||||
[ struct utsname *res; char *domain;
|
||||
(void)uname(res); if (res != 0) { domain = res->domainname; } ],
|
||||
[ac_cv_have_uname_domainname_field=true],
|
||||
[ac_cv_have_uname_domainname_field=false])])
|
||||
|
||||
if test "$ac_cv_have_uname_domainname_field" = "true"; then
|
||||
AC_DEFINE(HAVE_UNAME_DOMAINNAME_FIELD)
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(for uname.__domainname)
|
||||
AC_CACHE_VAL(ac_cv_have_uname_us_domainname_field,
|
||||
[AC_TRY_COMPILE([#include <sys/utsname.h>],
|
||||
[ struct utsname *res; char *domain;
|
||||
(void)uname(res); if (res != 0) { domain = res->__domainname; } ],
|
||||
[ac_cv_have_uname_us_domainname_field=true],
|
||||
[ac_cv_have_uname_us_domainname_field=false])])
|
||||
|
||||
if test "$ac_cv_have_uname_us_domainname_field" = "true"; then
|
||||
AC_DEFINE(HAVE_UNAME_US_DOMAINNAME_FIELD)
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
MOZ_CXX11
|
||||
|
||||
AC_LANG_C
|
||||
@ -3146,23 +3071,6 @@ dnl AC_CHECK_LIB(resolv, res_ninit, AC_DEFINE(HAVE_RES_NINIT)))
|
||||
fi
|
||||
|
||||
AC_LANG_CPLUSPLUS
|
||||
AC_CACHE_CHECK(
|
||||
[for gnu_get_libc_version()],
|
||||
ac_cv_func_gnu_get_libc_version,
|
||||
[AC_TRY_LINK([
|
||||
#ifdef HAVE_GNU_LIBC_VERSION_H
|
||||
#include <gnu/libc-version.h>
|
||||
#endif
|
||||
],
|
||||
[const char *glibc_version = gnu_get_libc_version();],
|
||||
[ac_cv_func_gnu_get_libc_version=yes],
|
||||
[ac_cv_func_gnu_get_libc_version=no]
|
||||
)]
|
||||
)
|
||||
|
||||
if test "$ac_cv_func_gnu_get_libc_version" = "yes"; then
|
||||
AC_DEFINE(HAVE_GNU_GET_LIBC_VERSION)
|
||||
fi
|
||||
|
||||
case $target_os in
|
||||
darwin*|mingw*|os2*)
|
||||
@ -6978,28 +6886,6 @@ if test -z "$MOZ_MEMORY"; then
|
||||
;;
|
||||
esac
|
||||
else
|
||||
dnl Don't try to run compiler tests on Windows
|
||||
if test "$OS_ARCH" = "WINNT"; then
|
||||
if test -z "$HAVE_64BIT_OS"; then
|
||||
AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 2)
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 3)
|
||||
fi
|
||||
else
|
||||
AC_CHECK_SIZEOF([int *], [4])
|
||||
case "${ac_cv_sizeof_int_p}" in
|
||||
4)
|
||||
AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 2)
|
||||
;;
|
||||
8)
|
||||
AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 3)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([Unexpected pointer size])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
AC_DEFINE(MOZ_MEMORY)
|
||||
if test -n "$MOZ_JEMALLOC3"; then
|
||||
AC_DEFINE(MOZ_JEMALLOC3)
|
||||
|
@ -1042,7 +1042,7 @@ CanvasRenderingContext2D::Render(gfxContext *ctx, GraphicsFilter aFilter, uint32
|
||||
if (!(aFlags & RenderFlagPremultAlpha)) {
|
||||
nsRefPtr<gfxASurface> curSurface = ctx->CurrentSurface();
|
||||
nsRefPtr<gfxImageSurface> gis = curSurface->GetAsImageSurface();
|
||||
NS_ABORT_IF_FALSE(gis, "If non-premult alpha, must be able to get image surface!");
|
||||
MOZ_ASSERT(gis, "If non-premult alpha, must be able to get image surface!");
|
||||
|
||||
gfxUtils::UnpremultiplyImageSurface(gis);
|
||||
}
|
||||
@ -3584,7 +3584,7 @@ CanvasRenderingContext2D::EnsureErrorTarget()
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> errorTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(IntSize(1, 1), FORMAT_B8G8R8A8);
|
||||
NS_ABORT_IF_FALSE(errorTarget, "Failed to allocate the error target!");
|
||||
MOZ_ASSERT(errorTarget, "Failed to allocate the error target!");
|
||||
|
||||
sErrorTarget = errorTarget;
|
||||
NS_ADDREF(sErrorTarget);
|
||||
|
@ -121,8 +121,7 @@ WebGLContext::WebGLContext()
|
||||
|
||||
mShaderValidation = true;
|
||||
|
||||
mBlackTexturesAreInitialized = false;
|
||||
mFakeBlackStatus = DoNotNeedFakeBlack;
|
||||
mFakeBlackStatus = WebGLContextFakeBlackStatus::NotNeeded;
|
||||
|
||||
mVertexAttrib0Vector[0] = 0;
|
||||
mVertexAttrib0Vector[1] = 0;
|
||||
@ -134,7 +133,7 @@ WebGLContext::WebGLContext()
|
||||
mFakeVertexAttrib0BufferObjectVector[3] = 1;
|
||||
mFakeVertexAttrib0BufferObjectSize = 0;
|
||||
mFakeVertexAttrib0BufferObject = 0;
|
||||
mFakeVertexAttrib0BufferStatus = VertexAttrib0Status::Default;
|
||||
mFakeVertexAttrib0BufferStatus = WebGLVertexAttrib0Status::Default;
|
||||
|
||||
// these are de default values, see 6.2 State tables in the OpenGL ES 2.0.25 spec
|
||||
mColorWriteMask[0] = 1;
|
||||
@ -264,11 +263,10 @@ WebGLContext::DestroyResourcesAndContext()
|
||||
while (!mQueries.isEmpty())
|
||||
mQueries.getLast()->DeleteOnce();
|
||||
|
||||
if (mBlackTexturesAreInitialized) {
|
||||
gl->fDeleteTextures(1, &mBlackTexture2D);
|
||||
gl->fDeleteTextures(1, &mBlackTextureCubeMap);
|
||||
mBlackTexturesAreInitialized = false;
|
||||
}
|
||||
mBlackOpaqueTexture2D = nullptr;
|
||||
mBlackOpaqueTextureCubeMap = nullptr;
|
||||
mBlackTransparentTexture2D = nullptr;
|
||||
mBlackTransparentTextureCubeMap = nullptr;
|
||||
|
||||
if (mFakeVertexAttrib0BufferObject) {
|
||||
gl->fDeleteBuffers(1, &mFakeVertexAttrib0BufferObject);
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/Scoped.h"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#include "ForceDiscreteGPUHelperCGL.h"
|
||||
@ -83,8 +84,6 @@ namespace gfx {
|
||||
class SourceSurface;
|
||||
}
|
||||
|
||||
using WebGLTexelConversions::WebGLTexelFormat;
|
||||
|
||||
WebGLTexelFormat GetWebGLTexelFormat(GLenum format, GLenum type);
|
||||
|
||||
struct WebGLContextOptions {
|
||||
@ -798,15 +797,17 @@ private:
|
||||
// -----------------------------------------------------------------------------
|
||||
// PROTECTED
|
||||
protected:
|
||||
void SetDontKnowIfNeedFakeBlack() {
|
||||
mFakeBlackStatus = DontKnowIfNeedFakeBlack;
|
||||
void SetFakeBlackStatus(WebGLContextFakeBlackStatus x) {
|
||||
mFakeBlackStatus = x;
|
||||
}
|
||||
// Returns the current fake-black-status, except if it was Unknown,
|
||||
// in which case this function resolves it first, so it never returns Unknown.
|
||||
WebGLContextFakeBlackStatus ResolvedFakeBlackStatus();
|
||||
|
||||
bool NeedFakeBlack();
|
||||
void BindFakeBlackTextures();
|
||||
void UnbindFakeBlackTextures();
|
||||
|
||||
int WhatDoesVertexAttrib0Need();
|
||||
WebGLVertexAttrib0Status WhatDoesVertexAttrib0Need();
|
||||
bool DoFakeVertexAttrib0(GLuint vertexCount);
|
||||
void UndoFakeVertexAttrib0();
|
||||
void InvalidateFakeVertexAttrib0();
|
||||
@ -1090,16 +1091,35 @@ protected:
|
||||
uint32_t mPixelStorePackAlignment, mPixelStoreUnpackAlignment, mPixelStoreColorspaceConversion;
|
||||
bool mPixelStoreFlipY, mPixelStorePremultiplyAlpha;
|
||||
|
||||
FakeBlackStatus mFakeBlackStatus;
|
||||
WebGLContextFakeBlackStatus mFakeBlackStatus;
|
||||
|
||||
GLuint mBlackTexture2D, mBlackTextureCubeMap;
|
||||
bool mBlackTexturesAreInitialized;
|
||||
class FakeBlackTexture
|
||||
{
|
||||
gl::GLContext* mGL;
|
||||
GLuint mGLName;
|
||||
|
||||
public:
|
||||
FakeBlackTexture(gl::GLContext* gl, GLenum target, GLenum format);
|
||||
~FakeBlackTexture();
|
||||
GLuint GLName() const { return mGLName; }
|
||||
};
|
||||
|
||||
ScopedDeletePtr<FakeBlackTexture> mBlackOpaqueTexture2D,
|
||||
mBlackOpaqueTextureCubeMap,
|
||||
mBlackTransparentTexture2D,
|
||||
mBlackTransparentTextureCubeMap;
|
||||
|
||||
void BindFakeBlackTexturesHelper(
|
||||
GLenum target,
|
||||
const nsTArray<WebGLRefPtr<WebGLTexture> >& boundTexturesArray,
|
||||
ScopedDeletePtr<FakeBlackTexture> & opaqueTextureScopedPtr,
|
||||
ScopedDeletePtr<FakeBlackTexture> & transparentTextureScopedPtr);
|
||||
|
||||
GLfloat mVertexAttrib0Vector[4];
|
||||
GLfloat mFakeVertexAttrib0BufferObjectVector[4];
|
||||
size_t mFakeVertexAttrib0BufferObjectSize;
|
||||
GLuint mFakeVertexAttrib0BufferObject;
|
||||
int mFakeVertexAttrib0BufferStatus;
|
||||
WebGLVertexAttrib0Status mFakeVertexAttrib0BufferStatus;
|
||||
|
||||
GLint mStencilRefFront, mStencilRefBack;
|
||||
GLuint mStencilValueMaskFront, mStencilValueMaskBack,
|
||||
|
@ -383,8 +383,8 @@ WebGLContext::DeleteBuffer(WebGLBuffer *buffer)
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxVertexAttribs; i++) {
|
||||
if (mBoundVertexArray->mAttribBuffers[i].buf == buffer)
|
||||
mBoundVertexArray->mAttribBuffers[i].buf = nullptr;
|
||||
if (mBoundVertexArray->HasAttrib(i) && mBoundVertexArray->mAttribs[i].buf == buffer)
|
||||
mBoundVertexArray->mAttribs[i].buf = nullptr;
|
||||
}
|
||||
|
||||
buffer->RequestDelete();
|
||||
@ -481,7 +481,7 @@ WebGLContext::CheckedBufferData(GLenum target,
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
|
||||
}
|
||||
NS_ABORT_IF_FALSE(boundBuffer != nullptr, "no buffer bound for this target");
|
||||
MOZ_ASSERT(boundBuffer != nullptr, "no buffer bound for this target");
|
||||
|
||||
bool sizeChanges = uint32_t(size) != boundBuffer->ByteLength();
|
||||
if (sizeChanges) {
|
||||
|
@ -180,6 +180,13 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
|
||||
else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_depth_texture")) {
|
||||
ext = WEBGL_depth_texture;
|
||||
}
|
||||
|
||||
if (ext != WebGLExtensionID_unknown_extension) {
|
||||
GenerateWarning("getExtension('%s'): MOZ_ prefixed WebGL extension strings are deprecated. "
|
||||
"Support for them will be removed in the future. Use unprefixed extension strings. "
|
||||
"To get draft extensions, set the webgl.enable-draft-extensions preference.",
|
||||
name.get());
|
||||
}
|
||||
}
|
||||
|
||||
if (ext == WebGLExtensionID_unknown_extension) {
|
||||
|
@ -30,7 +30,7 @@ WebGLContext::Clear(GLbitfield mask)
|
||||
}
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
|
||||
return ErrorInvalidFramebufferOperation("clear: incomplete framebuffer");
|
||||
|
||||
gl->fClear(mask);
|
||||
|
@ -52,15 +52,58 @@ using namespace mozilla::gl;
|
||||
static bool BaseTypeAndSizeFromUniformType(GLenum uType, GLenum *baseType, GLint *unitSize);
|
||||
static GLenum InternalFormatForFormatAndType(GLenum format, GLenum type, bool isGLES2);
|
||||
|
||||
//
|
||||
// WebGL API
|
||||
//
|
||||
|
||||
inline const WebGLRectangleObject *WebGLContext::FramebufferRectangleObject() const {
|
||||
return mBoundFramebuffer ? mBoundFramebuffer->RectangleObject()
|
||||
: static_cast<const WebGLRectangleObject*>(this);
|
||||
}
|
||||
|
||||
WebGLContext::FakeBlackTexture::FakeBlackTexture(GLContext *gl, GLenum target, GLenum format)
|
||||
: mGL(gl)
|
||||
, mGLName(0)
|
||||
{
|
||||
MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D || target == LOCAL_GL_TEXTURE_CUBE_MAP);
|
||||
MOZ_ASSERT(format == LOCAL_GL_RGB || format == LOCAL_GL_RGBA);
|
||||
|
||||
mGL->MakeCurrent();
|
||||
GLuint formerBinding = 0;
|
||||
gl->GetUIntegerv(target == LOCAL_GL_TEXTURE_2D
|
||||
? LOCAL_GL_TEXTURE_BINDING_2D
|
||||
: LOCAL_GL_TEXTURE_BINDING_CUBE_MAP,
|
||||
&formerBinding);
|
||||
gl->fGenTextures(1, &mGLName);
|
||||
gl->fBindTexture(target, mGLName);
|
||||
|
||||
// we allocate our zeros on the heap, and we overallocate (16 bytes instead of 4)
|
||||
// to minimize the risk of running into a driver bug in texImage2D, as it is
|
||||
// a bit unusual maybe to create 1x1 textures, and the stack may not have the alignment
|
||||
// that texImage2D expects.
|
||||
void* zeros = calloc(1, 16);
|
||||
if (target == LOCAL_GL_TEXTURE_2D) {
|
||||
gl->fTexImage2D(target, 0, format, 1, 1,
|
||||
0, format, LOCAL_GL_UNSIGNED_BYTE, zeros);
|
||||
} else {
|
||||
for (GLuint i = 0; i < 6; ++i) {
|
||||
gl->fTexImage2D(LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format, 1, 1,
|
||||
0, format, LOCAL_GL_UNSIGNED_BYTE, zeros);
|
||||
}
|
||||
}
|
||||
free(zeros);
|
||||
|
||||
gl->fBindTexture(target, formerBinding);
|
||||
}
|
||||
|
||||
WebGLContext::FakeBlackTexture::~FakeBlackTexture()
|
||||
{
|
||||
if (mGL) {
|
||||
mGL->MakeCurrent();
|
||||
mGL->fDeleteTextures(1, &mGLName);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// WebGL API
|
||||
//
|
||||
|
||||
void
|
||||
WebGLContext::ActiveTexture(GLenum texture)
|
||||
{
|
||||
@ -191,31 +234,47 @@ WebGLContext::BindRenderbuffer(GLenum target, WebGLRenderbuffer *wrb)
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BindTexture(GLenum target, WebGLTexture *tex)
|
||||
WebGLContext::BindTexture(GLenum target, WebGLTexture *newTex)
|
||||
{
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateObjectAllowDeletedOrNull("bindTexture", tex))
|
||||
if (!ValidateObjectAllowDeletedOrNull("bindTexture", newTex))
|
||||
return;
|
||||
|
||||
// silently ignore a deleted texture
|
||||
if (tex && tex->IsDeleted())
|
||||
if (newTex && newTex->IsDeleted())
|
||||
return;
|
||||
|
||||
WebGLRefPtr<WebGLTexture>* currentTexPtr = nullptr;
|
||||
|
||||
if (target == LOCAL_GL_TEXTURE_2D) {
|
||||
mBound2DTextures[mActiveTexture] = tex;
|
||||
currentTexPtr = &mBound2DTextures[mActiveTexture];
|
||||
} else if (target == LOCAL_GL_TEXTURE_CUBE_MAP) {
|
||||
mBoundCubeMapTextures[mActiveTexture] = tex;
|
||||
currentTexPtr = &mBoundCubeMapTextures[mActiveTexture];
|
||||
} else {
|
||||
return ErrorInvalidEnumInfo("bindTexture: target", target);
|
||||
}
|
||||
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
WebGLTextureFakeBlackStatus currentTexFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded;
|
||||
if (*currentTexPtr) {
|
||||
currentTexFakeBlackStatus = (*currentTexPtr)->ResolvedFakeBlackStatus();
|
||||
}
|
||||
WebGLTextureFakeBlackStatus newTexFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded;
|
||||
if (newTex) {
|
||||
newTexFakeBlackStatus = newTex->ResolvedFakeBlackStatus();
|
||||
}
|
||||
|
||||
*currentTexPtr = newTex;
|
||||
|
||||
if (currentTexFakeBlackStatus != newTexFakeBlackStatus) {
|
||||
SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown);
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (tex)
|
||||
tex->Bind(target);
|
||||
if (newTex)
|
||||
newTex->Bind(target);
|
||||
else
|
||||
gl->fBindTexture(target, 0 /* == texturename */);
|
||||
}
|
||||
@ -508,7 +567,7 @@ WebGLContext::CopyTexImage2D(GLenum target,
|
||||
return ErrorInvalidOperation("copyTexImage2D: a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
|
||||
|
||||
if (mBoundFramebuffer)
|
||||
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
|
||||
return ErrorInvalidFramebufferOperation("copyTexImage2D: incomplete framebuffer");
|
||||
|
||||
WebGLTexture *tex = activeBoundTextureForTarget(target);
|
||||
@ -537,12 +596,13 @@ WebGLContext::CopyTexImage2D(GLenum target,
|
||||
if (error) {
|
||||
GenerateWarning("copyTexImage2D generated error %s", ErrorName(error));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CopyTexSubImage2D_base(target, level, internalformat, 0, 0, x, y, width, height, false);
|
||||
}
|
||||
|
||||
tex->SetImageInfo(target, level, width, height, internalformat, type);
|
||||
|
||||
tex->SetImageInfo(target, level, width, height, internalformat, type,
|
||||
WebGLImageDataStatus::InitializedImageData);
|
||||
}
|
||||
|
||||
void
|
||||
@ -617,9 +677,13 @@ WebGLContext::CopyTexSubImage2D(GLenum target,
|
||||
return ErrorInvalidOperation("copyTexSubImage2D: a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
|
||||
|
||||
if (mBoundFramebuffer)
|
||||
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
|
||||
return ErrorInvalidFramebufferOperation("copyTexSubImage2D: incomplete framebuffer");
|
||||
|
||||
if (imageInfo.HasUninitializedImageData()) {
|
||||
tex->DoDeferredImageInitialization(target, level);
|
||||
}
|
||||
|
||||
return CopyTexSubImage2D_base(target, level, format, xoffset, yoffset, x, y, width, height, true);
|
||||
}
|
||||
|
||||
@ -805,7 +869,7 @@ WebGLContext::DepthRange(GLfloat zNear, GLfloat zFar)
|
||||
gl->fDepthRange(zNear, zFar);
|
||||
}
|
||||
|
||||
int
|
||||
WebGLVertexAttrib0Status
|
||||
WebGLContext::WhatDoesVertexAttrib0Need()
|
||||
{
|
||||
// here we may assume that mCurrentProgram != null
|
||||
@ -813,24 +877,24 @@ WebGLContext::WhatDoesVertexAttrib0Need()
|
||||
// work around Mac OSX crash, see bug 631420
|
||||
#ifdef XP_MACOSX
|
||||
if (gl->WorkAroundDriverBugs() &&
|
||||
mBoundVertexArray->mAttribBuffers[0].enabled &&
|
||||
mBoundVertexArray->IsAttribArrayEnabled(0) &&
|
||||
!mCurrentProgram->IsAttribInUse(0))
|
||||
{
|
||||
return VertexAttrib0Status::EmulatedUninitializedArray;
|
||||
return WebGLVertexAttrib0Status::EmulatedUninitializedArray;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (gl->IsGLES2() || mBoundVertexArray->mAttribBuffers[0].enabled) ? VertexAttrib0Status::Default
|
||||
: mCurrentProgram->IsAttribInUse(0) ? VertexAttrib0Status::EmulatedInitializedArray
|
||||
: VertexAttrib0Status::EmulatedUninitializedArray;
|
||||
return (gl->IsGLES2() || mBoundVertexArray->IsAttribArrayEnabled(0)) ? WebGLVertexAttrib0Status::Default
|
||||
: mCurrentProgram->IsAttribInUse(0) ? WebGLVertexAttrib0Status::EmulatedInitializedArray
|
||||
: WebGLVertexAttrib0Status::EmulatedUninitializedArray;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount)
|
||||
{
|
||||
int whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
|
||||
WebGLVertexAttrib0Status whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
|
||||
|
||||
if (whatDoesAttrib0Need == VertexAttrib0Status::Default)
|
||||
if (whatDoesAttrib0Need == WebGLVertexAttrib0Status::Default)
|
||||
return true;
|
||||
|
||||
if (!mAlreadyWarnedAboutFakeVertexAttrib0) {
|
||||
@ -860,8 +924,8 @@ WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount)
|
||||
// we don't need it to be, then consider it OK
|
||||
bool vertexAttrib0BufferStatusOK =
|
||||
mFakeVertexAttrib0BufferStatus == whatDoesAttrib0Need ||
|
||||
(mFakeVertexAttrib0BufferStatus == VertexAttrib0Status::EmulatedInitializedArray &&
|
||||
whatDoesAttrib0Need == VertexAttrib0Status::EmulatedUninitializedArray);
|
||||
(mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray &&
|
||||
whatDoesAttrib0Need == WebGLVertexAttrib0Status::EmulatedUninitializedArray);
|
||||
|
||||
if (!vertexAttrib0BufferStatusOK ||
|
||||
mFakeVertexAttrib0BufferObjectSize < dataSize ||
|
||||
@ -882,7 +946,7 @@ WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount)
|
||||
GLenum error = LOCAL_GL_NO_ERROR;
|
||||
UpdateWebGLErrorAndClearGLError();
|
||||
|
||||
if (mFakeVertexAttrib0BufferStatus == VertexAttrib0Status::EmulatedInitializedArray) {
|
||||
if (mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray) {
|
||||
nsAutoArrayPtr<GLfloat> array(new GLfloat[4 * vertexCount]);
|
||||
for(size_t i = 0; i < vertexCount; ++i) {
|
||||
array[4 * i + 0] = mVertexAttrib0Vector[0];
|
||||
@ -915,106 +979,120 @@ WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount)
|
||||
void
|
||||
WebGLContext::UndoFakeVertexAttrib0()
|
||||
{
|
||||
int whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
|
||||
WebGLVertexAttrib0Status whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
|
||||
|
||||
if (whatDoesAttrib0Need == VertexAttrib0Status::Default)
|
||||
if (whatDoesAttrib0Need == WebGLVertexAttrib0Status::Default)
|
||||
return;
|
||||
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundVertexArray->mAttribBuffers[0].buf ? mBoundVertexArray->mAttribBuffers[0].buf->GLName() : 0);
|
||||
gl->fVertexAttribPointer(0,
|
||||
mBoundVertexArray->mAttribBuffers[0].size,
|
||||
mBoundVertexArray->mAttribBuffers[0].type,
|
||||
mBoundVertexArray->mAttribBuffers[0].normalized,
|
||||
mBoundVertexArray->mAttribBuffers[0].stride,
|
||||
reinterpret_cast<const GLvoid *>(mBoundVertexArray->mAttribBuffers[0].byteOffset));
|
||||
if (mBoundVertexArray->HasAttrib(0) && mBoundVertexArray->mAttribs[0].buf) {
|
||||
const WebGLVertexAttribData& attrib0 = mBoundVertexArray->mAttribs[0];
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, attrib0.buf->GLName());
|
||||
gl->fVertexAttribPointer(0,
|
||||
attrib0.size,
|
||||
attrib0.type,
|
||||
attrib0.normalized,
|
||||
attrib0.stride,
|
||||
reinterpret_cast<const GLvoid *>(attrib0.byteOffset));
|
||||
} else {
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::NeedFakeBlack()
|
||||
WebGLContextFakeBlackStatus
|
||||
WebGLContext::ResolvedFakeBlackStatus()
|
||||
{
|
||||
// handle this case first, it's the generic case
|
||||
if (mFakeBlackStatus == DoNotNeedFakeBlack)
|
||||
return false;
|
||||
if (MOZ_LIKELY(mFakeBlackStatus == WebGLContextFakeBlackStatus::NotNeeded))
|
||||
return mFakeBlackStatus;
|
||||
|
||||
if (mFakeBlackStatus == DoNeedFakeBlack)
|
||||
return true;
|
||||
if (mFakeBlackStatus == WebGLContextFakeBlackStatus::Needed)
|
||||
return mFakeBlackStatus;
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
|
||||
if ((mBound2DTextures[i] && mBound2DTextures[i]->NeedFakeBlack()) ||
|
||||
(mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->NeedFakeBlack()))
|
||||
if ((mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) ||
|
||||
(mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded))
|
||||
{
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
return true;
|
||||
mFakeBlackStatus = WebGLContextFakeBlackStatus::Needed;
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
}
|
||||
|
||||
// we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
|
||||
// that means that we do NOT need it.
|
||||
mFakeBlackStatus = DoNotNeedFakeBlack;
|
||||
return false;
|
||||
mFakeBlackStatus = WebGLContextFakeBlackStatus::NotNeeded;
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BindFakeBlackTexturesHelper(
|
||||
GLenum target,
|
||||
const nsTArray<WebGLRefPtr<WebGLTexture> > & boundTexturesArray,
|
||||
ScopedDeletePtr<FakeBlackTexture> & opaqueTextureScopedPtr,
|
||||
ScopedDeletePtr<FakeBlackTexture> & transparentTextureScopedPtr)
|
||||
{
|
||||
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
|
||||
if (!boundTexturesArray[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WebGLTextureFakeBlackStatus s = boundTexturesArray[i]->ResolvedFakeBlackStatus();
|
||||
MOZ_ASSERT(s != WebGLTextureFakeBlackStatus::Unknown);
|
||||
|
||||
if (MOZ_LIKELY(s == WebGLTextureFakeBlackStatus::NotNeeded)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool alpha = s == WebGLTextureFakeBlackStatus::UninitializedImageData &&
|
||||
FormatHasAlpha(boundTexturesArray[i]->ImageInfoBase().Format());
|
||||
ScopedDeletePtr<FakeBlackTexture>&
|
||||
blackTexturePtr = alpha
|
||||
? transparentTextureScopedPtr
|
||||
: opaqueTextureScopedPtr;
|
||||
|
||||
if (!blackTexturePtr) {
|
||||
GLenum format = alpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
|
||||
blackTexturePtr
|
||||
= new FakeBlackTexture(gl, target, format);
|
||||
}
|
||||
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
gl->fBindTexture(target,
|
||||
blackTexturePtr->GLName());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BindFakeBlackTextures()
|
||||
{
|
||||
// this is the generic case: try to return early
|
||||
if (!NeedFakeBlack())
|
||||
if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
|
||||
return;
|
||||
|
||||
if (!mBlackTexturesAreInitialized) {
|
||||
GLuint bound2DTex = 0;
|
||||
GLuint boundCubeTex = 0;
|
||||
gl->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, (GLint*) &bound2DTex);
|
||||
gl->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_CUBE_MAP, (GLint*) &boundCubeTex);
|
||||
|
||||
const uint8_t black[] = {0, 0, 0, 255};
|
||||
|
||||
gl->fGenTextures(1, &mBlackTexture2D);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBlackTexture2D);
|
||||
gl->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, 1, 1,
|
||||
0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, &black);
|
||||
|
||||
gl->fGenTextures(1, &mBlackTextureCubeMap);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBlackTextureCubeMap);
|
||||
for (GLuint i = 0; i < 6; ++i) {
|
||||
gl->fTexImage2D(LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, LOCAL_GL_RGBA, 1, 1,
|
||||
0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, &black);
|
||||
}
|
||||
|
||||
// Reset bound textures
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, bound2DTex);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, boundCubeTex);
|
||||
|
||||
mBlackTexturesAreInitialized = true;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
|
||||
if (mBound2DTextures[i] && mBound2DTextures[i]->NeedFakeBlack()) {
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBlackTexture2D);
|
||||
}
|
||||
if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->NeedFakeBlack()) {
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBlackTextureCubeMap);
|
||||
}
|
||||
}
|
||||
BindFakeBlackTexturesHelper(LOCAL_GL_TEXTURE_2D,
|
||||
mBound2DTextures,
|
||||
mBlackOpaqueTexture2D,
|
||||
mBlackTransparentTexture2D);
|
||||
BindFakeBlackTexturesHelper(LOCAL_GL_TEXTURE_CUBE_MAP,
|
||||
mBoundCubeMapTextures,
|
||||
mBlackOpaqueTextureCubeMap,
|
||||
mBlackTransparentTextureCubeMap);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::UnbindFakeBlackTextures()
|
||||
{
|
||||
// this is the generic case: try to return early
|
||||
if (!NeedFakeBlack())
|
||||
if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
|
||||
return;
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
|
||||
if (mBound2DTextures[i] && mBound2DTextures[i]->NeedFakeBlack()) {
|
||||
if (mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBound2DTextures[i]->GLName());
|
||||
}
|
||||
if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->NeedFakeBlack()) {
|
||||
if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBoundCubeMapTextures[i]->GLName());
|
||||
}
|
||||
@ -1951,7 +2029,7 @@ WebGLContext::IsTexture(WebGLTexture *tex)
|
||||
// Try to bind an attribute that is an array to location 0:
|
||||
bool WebGLContext::BindArrayAttribToLocation0(WebGLProgram *program)
|
||||
{
|
||||
if (mBoundVertexArray->mAttribBuffers[0].enabled) {
|
||||
if (mBoundVertexArray->IsAttribArrayEnabled(0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1962,7 +2040,7 @@ bool WebGLContext::BindArrayAttribToLocation0(WebGLProgram *program)
|
||||
itr != program->mActiveAttribMap.end();
|
||||
itr++) {
|
||||
int32_t index = itr->first;
|
||||
if (mBoundVertexArray->mAttribBuffers[index].enabled &&
|
||||
if (mBoundVertexArray->IsAttribArrayEnabled(index) &&
|
||||
index < leastArrayLocation)
|
||||
{
|
||||
leastArrayLocation = index;
|
||||
@ -2084,7 +2162,7 @@ WebGLContext::LinkProgram(WebGLProgram *program)
|
||||
shaderTypeName = "fragment";
|
||||
} else {
|
||||
// should have been validated earlier
|
||||
NS_ABORT();
|
||||
MOZ_ASSERT(false);
|
||||
shaderTypeName = "<unknown>";
|
||||
}
|
||||
|
||||
@ -2254,7 +2332,7 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
// prevent readback of arbitrary video memory through uninitialized renderbuffers!
|
||||
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
|
||||
return ErrorInvalidFramebufferOperation("readPixels: incomplete framebuffer");
|
||||
}
|
||||
// Now that the errors are out of the way, on to actually reading
|
||||
@ -2440,7 +2518,7 @@ WebGLContext::RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei
|
||||
mBoundRenderbuffer->SetInternalFormat(internalformat);
|
||||
mBoundRenderbuffer->SetInternalFormatForGL(internalformatForGL);
|
||||
mBoundRenderbuffer->setDimensions(width, height);
|
||||
mBoundRenderbuffer->SetInitialized(false);
|
||||
mBoundRenderbuffer->SetImageDataStatus(WebGLImageDataStatus::UninitializedImageData);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2589,16 +2667,16 @@ WebGLContext::SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromE
|
||||
|
||||
switch (surf->Format()) {
|
||||
case gfxImageFormatARGB32:
|
||||
*format = WebGLTexelConversions::BGRA8; // careful, our ARGB means BGRA
|
||||
*format = WebGLTexelFormat::BGRA8; // careful, our ARGB means BGRA
|
||||
break;
|
||||
case gfxImageFormatRGB24:
|
||||
*format = WebGLTexelConversions::BGRX8; // careful, our RGB24 is not tightly packed. Whence BGRX8.
|
||||
*format = WebGLTexelFormat::BGRX8; // careful, our RGB24 is not tightly packed. Whence BGRX8.
|
||||
break;
|
||||
case gfxImageFormatA8:
|
||||
*format = WebGLTexelConversions::A8;
|
||||
*format = WebGLTexelFormat::A8;
|
||||
break;
|
||||
case gfxImageFormatRGB16_565:
|
||||
*format = WebGLTexelConversions::RGB565;
|
||||
*format = WebGLTexelFormat::RGB565;
|
||||
break;
|
||||
default:
|
||||
NS_ASSERTION(false, "Unsupported image format. Unimplemented.");
|
||||
@ -3303,7 +3381,8 @@ WebGLContext::CompressedTexImage2D(GLenum target, GLint level, GLenum internalfo
|
||||
}
|
||||
|
||||
gl->fCompressedTexImage2D(target, level, internalformat, width, height, border, byteLength, view.Data());
|
||||
tex->SetImageInfo(target, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE);
|
||||
tex->SetImageInfo(target, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE,
|
||||
WebGLImageDataStatus::InitializedImageData);
|
||||
|
||||
ReattachTextureToAnyFramebufferToWorkAroundBugs(tex, level);
|
||||
}
|
||||
@ -3401,6 +3480,10 @@ WebGLContext::CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
|
||||
}
|
||||
}
|
||||
|
||||
if (imageInfo.HasUninitializedImageData()) {
|
||||
tex->DoDeferredImageInitialization(target, level);
|
||||
}
|
||||
|
||||
gl->fCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, byteLength, view.Data());
|
||||
|
||||
return;
|
||||
@ -3588,7 +3671,7 @@ GLenum WebGLContext::CheckedTexImage2D(GLenum target,
|
||||
const GLvoid *data)
|
||||
{
|
||||
WebGLTexture *tex = activeBoundTextureForTarget(target);
|
||||
NS_ABORT_IF_FALSE(tex != nullptr, "no texture bound");
|
||||
MOZ_ASSERT(tex != nullptr, "no texture bound");
|
||||
|
||||
bool sizeMayChange = true;
|
||||
|
||||
@ -3676,7 +3759,7 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
||||
return;
|
||||
|
||||
WebGLTexelFormat dstFormat = GetWebGLTexelFormat(format, type);
|
||||
WebGLTexelFormat actualSrcFormat = srcFormat == WebGLTexelConversions::Auto ? dstFormat : srcFormat;
|
||||
WebGLTexelFormat actualSrcFormat = srcFormat == WebGLTexelFormat::Auto ? dstFormat : srcFormat;
|
||||
|
||||
uint32_t srcTexelSize = WebGLTexelConversions::TexelBytesForFormat(actualSrcFormat);
|
||||
|
||||
@ -3710,6 +3793,8 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
||||
|
||||
GLenum error = LOCAL_GL_NO_ERROR;
|
||||
|
||||
WebGLImageDataStatus imageInfoStatusIfSuccess = WebGLImageDataStatus::NoImageData;
|
||||
|
||||
if (byteLength) {
|
||||
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
|
||||
|
||||
@ -3737,76 +3822,11 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
||||
error = CheckedTexImage2D(target, level, internalformat,
|
||||
width, height, border, format, type, convertedData);
|
||||
}
|
||||
imageInfoStatusIfSuccess = WebGLImageDataStatus::InitializedImageData;
|
||||
} else {
|
||||
if (isDepthTexture && !gl->IsSupported(GLFeature::depth_texture)) {
|
||||
// There's only one way that we can we supporting depth textures without
|
||||
// supporting the regular depth_texture feature set: that's
|
||||
// with ANGLE_depth_texture.
|
||||
|
||||
// It should be impossible to get here without ANGLE_depth_texture support
|
||||
MOZ_ASSERT(gl->IsExtensionSupported(GLContext::ANGLE_depth_texture));
|
||||
// It should be impossible to get here with a target other than TEXTURE_2D,
|
||||
// a nonzero level, or non-null data
|
||||
MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D && level == 0 && data == nullptr);
|
||||
|
||||
// We start by calling texImage2D with null data, giving us an uninitialized texture,
|
||||
// which is all it can give us in this case.
|
||||
error = CheckedTexImage2D(LOCAL_GL_TEXTURE_2D, 0, internalformat, width, height,
|
||||
border, format, type, nullptr);
|
||||
|
||||
// We then proceed to initializing the texture by assembling a FBO.
|
||||
// We make it a color-less FBO, which isn't supported everywhere, but we should be
|
||||
// fine because we only need this to be successful on ANGLE which is said to support
|
||||
// that. Still, we want to gracefully handle failure in case the FBO is incomplete.
|
||||
|
||||
bool success = false;
|
||||
GLuint fb = 0;
|
||||
|
||||
// dummy do {...} while to be able to break
|
||||
do {
|
||||
gl->fGenFramebuffers(1, &fb);
|
||||
if (!fb)
|
||||
break;
|
||||
|
||||
ScopedBindFramebuffer autoBindFB(gl, fb);
|
||||
|
||||
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_DEPTH_ATTACHMENT,
|
||||
LOCAL_GL_TEXTURE_2D,
|
||||
tex->GLName(),
|
||||
0);
|
||||
if (format == LOCAL_GL_DEPTH_STENCIL) {
|
||||
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_STENCIL_ATTACHMENT,
|
||||
LOCAL_GL_TEXTURE_2D,
|
||||
tex->GLName(),
|
||||
0);
|
||||
}
|
||||
if (gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
break;
|
||||
|
||||
gl->ClearSafely();
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
gl->fDeleteFramebuffers(1, &fb);
|
||||
|
||||
if (!success) {
|
||||
return ErrorOutOfMemory("texImage2D: sorry, ran out of ways to initialize a depth texture.");
|
||||
}
|
||||
} else {
|
||||
// We need some zero pages, because GL doesn't guarantee the
|
||||
// contents of a texture allocated with nullptr data.
|
||||
// Hopefully calloc will just mmap zero pages here.
|
||||
void *tempZeroData = calloc(1, bytesNeeded);
|
||||
if (!tempZeroData)
|
||||
return ErrorOutOfMemory("texImage2D: could not allocate %d bytes (for zero fill)", bytesNeeded);
|
||||
|
||||
error = CheckedTexImage2D(target, level, internalformat,
|
||||
width, height, border, format, type, tempZeroData);
|
||||
|
||||
free(tempZeroData);
|
||||
}
|
||||
error = CheckedTexImage2D(target, level, internalformat,
|
||||
width, height, border, format, type, nullptr);
|
||||
imageInfoStatusIfSuccess = WebGLImageDataStatus::UninitializedImageData;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
@ -3814,7 +3834,12 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
|
||||
return;
|
||||
}
|
||||
|
||||
tex->SetImageInfo(target, level, width, height, format, type);
|
||||
// in all of the code paths above, we should have either initialized data,
|
||||
// or allocated data and left it uninitialized, but in any case we shouldn't
|
||||
// have NoImageData at this point.
|
||||
MOZ_ASSERT(imageInfoStatusIfSuccess != WebGLImageDataStatus::NoImageData);
|
||||
|
||||
tex->SetImageInfo(target, level, width, height, format, type, imageInfoStatusIfSuccess);
|
||||
|
||||
ReattachTextureToAnyFramebufferToWorkAroundBugs(tex, level);
|
||||
}
|
||||
@ -3832,7 +3857,7 @@ WebGLContext::TexImage2D(GLenum target, GLint level,
|
||||
pixels.IsNull() ? 0 : pixels.Value().Data(),
|
||||
pixels.IsNull() ? 0 : pixels.Value().Length(),
|
||||
pixels.IsNull() ? -1 : (int)JS_GetArrayBufferViewType(pixels.Value().Obj()),
|
||||
WebGLTexelConversions::Auto, false);
|
||||
WebGLTexelFormat::Auto, false);
|
||||
}
|
||||
|
||||
void
|
||||
@ -3852,7 +3877,7 @@ WebGLContext::TexImage2D(GLenum target, GLint level,
|
||||
return TexImage2D_base(target, level, internalformat, pixels->Width(),
|
||||
pixels->Height(), 4*pixels->Width(), 0,
|
||||
format, type, arr.Data(), arr.Length(), -1,
|
||||
WebGLTexelConversions::RGBA8, false);
|
||||
WebGLTexelFormat::RGBA8, false);
|
||||
}
|
||||
|
||||
|
||||
@ -3898,7 +3923,7 @@ WebGLContext::TexSubImage2D_base(GLenum target, GLint level,
|
||||
return;
|
||||
|
||||
WebGLTexelFormat dstFormat = GetWebGLTexelFormat(format, type);
|
||||
WebGLTexelFormat actualSrcFormat = srcFormat == WebGLTexelConversions::Auto ? dstFormat : srcFormat;
|
||||
WebGLTexelFormat actualSrcFormat = srcFormat == WebGLTexelFormat::Auto ? dstFormat : srcFormat;
|
||||
|
||||
uint32_t srcTexelSize = WebGLTexelConversions::TexelBytesForFormat(actualSrcFormat);
|
||||
|
||||
@ -3937,6 +3962,10 @@ WebGLContext::TexSubImage2D_base(GLenum target, GLint level,
|
||||
if (imageInfo.Format() != format || imageInfo.Type() != type)
|
||||
return ErrorInvalidOperation("texSubImage2D: format or type doesn't match the existing texture");
|
||||
|
||||
if (imageInfo.HasUninitializedImageData()) {
|
||||
tex->DoDeferredImageInitialization(target, level);
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
|
||||
@ -3984,7 +4013,7 @@ WebGLContext::TexSubImage2D(GLenum target, GLint level,
|
||||
width, height, 0, format, type,
|
||||
pixels.Value().Data(), pixels.Value().Length(),
|
||||
JS_GetArrayBufferViewType(pixels.Value().Obj()),
|
||||
WebGLTexelConversions::Auto, false);
|
||||
WebGLTexelFormat::Auto, false);
|
||||
}
|
||||
|
||||
void
|
||||
@ -4005,7 +4034,7 @@ WebGLContext::TexSubImage2D(GLenum target, GLint level,
|
||||
4*pixels->Width(), format, type,
|
||||
arr.Data(), arr.Length(),
|
||||
-1,
|
||||
WebGLTexelConversions::RGBA8, false);
|
||||
WebGLTexelFormat::RGBA8, false);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -4109,16 +4138,16 @@ WebGLTexelFormat mozilla::GetWebGLTexelFormat(GLenum format, GLenum type)
|
||||
if (format == LOCAL_GL_DEPTH_COMPONENT) {
|
||||
switch (type) {
|
||||
case LOCAL_GL_UNSIGNED_SHORT:
|
||||
return WebGLTexelConversions::D16;
|
||||
return WebGLTexelFormat::D16;
|
||||
case LOCAL_GL_UNSIGNED_INT:
|
||||
return WebGLTexelConversions::D32;
|
||||
return WebGLTexelFormat::D32;
|
||||
default:
|
||||
MOZ_CRASH("Invalid WebGL texture format/type?");
|
||||
}
|
||||
} else if (format == LOCAL_GL_DEPTH_STENCIL) {
|
||||
switch (type) {
|
||||
case LOCAL_GL_UNSIGNED_INT_24_8_EXT:
|
||||
return WebGLTexelConversions::D24S8;
|
||||
return WebGLTexelFormat::D24S8;
|
||||
default:
|
||||
MOZ_CRASH("Invalid WebGL texture format/type?");
|
||||
}
|
||||
@ -4128,47 +4157,47 @@ WebGLTexelFormat mozilla::GetWebGLTexelFormat(GLenum format, GLenum type)
|
||||
if (type == LOCAL_GL_UNSIGNED_BYTE) {
|
||||
switch (format) {
|
||||
case LOCAL_GL_RGBA:
|
||||
return WebGLTexelConversions::RGBA8;
|
||||
return WebGLTexelFormat::RGBA8;
|
||||
case LOCAL_GL_RGB:
|
||||
return WebGLTexelConversions::RGB8;
|
||||
return WebGLTexelFormat::RGB8;
|
||||
case LOCAL_GL_ALPHA:
|
||||
return WebGLTexelConversions::A8;
|
||||
return WebGLTexelFormat::A8;
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
return WebGLTexelConversions::R8;
|
||||
return WebGLTexelFormat::R8;
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
return WebGLTexelConversions::RA8;
|
||||
return WebGLTexelFormat::RA8;
|
||||
default:
|
||||
NS_ABORT_IF_FALSE(false, "Coding mistake?! Should never reach this point.");
|
||||
return WebGLTexelConversions::BadFormat;
|
||||
MOZ_ASSERT(false, "Coding mistake?! Should never reach this point.");
|
||||
return WebGLTexelFormat::BadFormat;
|
||||
}
|
||||
} else if (type == LOCAL_GL_FLOAT) {
|
||||
// OES_texture_float
|
||||
switch (format) {
|
||||
case LOCAL_GL_RGBA:
|
||||
return WebGLTexelConversions::RGBA32F;
|
||||
return WebGLTexelFormat::RGBA32F;
|
||||
case LOCAL_GL_RGB:
|
||||
return WebGLTexelConversions::RGB32F;
|
||||
return WebGLTexelFormat::RGB32F;
|
||||
case LOCAL_GL_ALPHA:
|
||||
return WebGLTexelConversions::A32F;
|
||||
return WebGLTexelFormat::A32F;
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
return WebGLTexelConversions::R32F;
|
||||
return WebGLTexelFormat::R32F;
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
return WebGLTexelConversions::RA32F;
|
||||
return WebGLTexelFormat::RA32F;
|
||||
default:
|
||||
NS_ABORT_IF_FALSE(false, "Coding mistake?! Should never reach this point.");
|
||||
return WebGLTexelConversions::BadFormat;
|
||||
MOZ_ASSERT(false, "Coding mistake?! Should never reach this point.");
|
||||
return WebGLTexelFormat::BadFormat;
|
||||
}
|
||||
} else {
|
||||
switch (type) {
|
||||
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
||||
return WebGLTexelConversions::RGBA4444;
|
||||
return WebGLTexelFormat::RGBA4444;
|
||||
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
||||
return WebGLTexelConversions::RGBA5551;
|
||||
return WebGLTexelFormat::RGBA5551;
|
||||
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
||||
return WebGLTexelConversions::RGB565;
|
||||
return WebGLTexelFormat::RGB565;
|
||||
default:
|
||||
NS_ABORT_IF_FALSE(false, "Coding mistake?! Should never reach this point.");
|
||||
return WebGLTexelConversions::BadFormat;
|
||||
MOZ_ASSERT(false, "Coding mistake?! Should never reach this point.");
|
||||
return WebGLTexelFormat::BadFormat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ WebGLContext::ErrorName(GLenum error)
|
||||
case LOCAL_GL_NO_ERROR:
|
||||
return "NO_ERROR";
|
||||
default:
|
||||
NS_ABORT();
|
||||
MOZ_ASSERT(false);
|
||||
return "[unknown WebGL error!]";
|
||||
}
|
||||
}
|
||||
@ -221,8 +221,7 @@ WebGLContext::IsTextureFormatCompressed(GLenum format)
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_NOTREACHED("Invalid WebGL texture format?");
|
||||
NS_ABORT();
|
||||
MOZ_ASSERT(false, "Invalid WebGL texture format?");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ WebGLProgram::UpdateInfo()
|
||||
mContext->gl->fGetActiveAttrib(mGLName, i, mAttribMaxNameLength, &attrnamelen, &attrsize, &attrtype, nameBuf);
|
||||
if (attrnamelen > 0) {
|
||||
GLint loc = mContext->gl->fGetAttribLocation(mGLName, nameBuf);
|
||||
NS_ABORT_IF_FALSE(loc >= 0, "major oops in managing the attributes of a WebGL program");
|
||||
MOZ_ASSERT(loc >= 0, "major oops in managing the attributes of a WebGL program");
|
||||
if (loc < mContext->mGLMaxVertexAttribs) {
|
||||
mAttribsInUse[loc] = true;
|
||||
} else {
|
||||
@ -491,7 +491,7 @@ uint32_t WebGLContext::GetBitsPerTexel(GLenum format, GLenum type)
|
||||
return 16;
|
||||
}
|
||||
|
||||
NS_ABORT();
|
||||
MOZ_ASSERT(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -766,7 +766,7 @@ WebGLContext::ValidateUniformSetter(const char* name, WebGLUniformLocation *loca
|
||||
|
||||
bool WebGLContext::ValidateAttribIndex(GLuint index, const char *info)
|
||||
{
|
||||
return mBoundVertexArray->EnsureAttribIndex(index, info);
|
||||
return mBoundVertexArray->EnsureAttrib(index, info);
|
||||
}
|
||||
|
||||
bool WebGLContext::ValidateStencilParamsForDrawCall()
|
||||
@ -998,7 +998,7 @@ WebGLContext::InitAndValidateGL()
|
||||
}
|
||||
|
||||
mDefaultVertexArray = new WebGLVertexArray(this);
|
||||
mDefaultVertexArray->mAttribBuffers.SetLength(mGLMaxVertexAttribs);
|
||||
mDefaultVertexArray->mAttribs.SetLength(mGLMaxVertexAttribs);
|
||||
mBoundVertexArray = mDefaultVertexArray;
|
||||
|
||||
return true;
|
||||
|
@ -196,7 +196,8 @@ WebGLContext::EnableVertexAttribArray(GLuint index)
|
||||
InvalidateBufferFetching();
|
||||
|
||||
gl->fEnableVertexAttribArray(index);
|
||||
mBoundVertexArray->mAttribBuffers[index].enabled = true;
|
||||
MOZ_ASSERT(mBoundVertexArray->HasAttrib(index)); // should have been validated earlier
|
||||
mBoundVertexArray->mAttribs[index].enabled = true;
|
||||
}
|
||||
|
||||
void
|
||||
@ -214,7 +215,8 @@ WebGLContext::DisableVertexAttribArray(GLuint index)
|
||||
if (index || gl->IsGLES2())
|
||||
gl->fDisableVertexAttribArray(index);
|
||||
|
||||
mBoundVertexArray->mAttribBuffers[index].enabled = false;
|
||||
MOZ_ASSERT(mBoundVertexArray->HasAttrib(index)); // should have been validated earlier
|
||||
mBoundVertexArray->mAttribs[index].enabled = false;
|
||||
}
|
||||
|
||||
|
||||
@ -225,7 +227,7 @@ WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
|
||||
if (IsContextLost())
|
||||
return JS::NullValue();
|
||||
|
||||
if (!mBoundVertexArray->EnsureAttribIndex(index, "getVertexAttrib"))
|
||||
if (!ValidateAttribIndex(index, "getVertexAttrib"))
|
||||
return JS::NullValue();
|
||||
|
||||
MakeContextCurrent();
|
||||
@ -233,12 +235,12 @@ WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
|
||||
switch (pname) {
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
|
||||
{
|
||||
return WebGLObjectAsJSValue(cx, mBoundVertexArray->mAttribBuffers[index].buf.get(), rv);
|
||||
return WebGLObjectAsJSValue(cx, mBoundVertexArray->mAttribs[index].buf.get(), rv);
|
||||
}
|
||||
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE:
|
||||
{
|
||||
return JS::Int32Value(mBoundVertexArray->mAttribBuffers[index].stride);
|
||||
return JS::Int32Value(mBoundVertexArray->mAttribs[index].stride);
|
||||
}
|
||||
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE:
|
||||
@ -246,7 +248,7 @@ WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
|
||||
if (!ValidateAttribIndex(index, "getVertexAttrib"))
|
||||
return JS::NullValue();
|
||||
|
||||
if (!mBoundVertexArray->mAttribBuffers[index].enabled)
|
||||
if (!mBoundVertexArray->mAttribs[index].enabled)
|
||||
return JS::Int32Value(4);
|
||||
|
||||
// Don't break; fall through.
|
||||
@ -265,7 +267,7 @@ WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
|
||||
{
|
||||
if (IsExtensionEnabled(ANGLE_instanced_arrays))
|
||||
{
|
||||
return JS::Int32Value(mBoundVertexArray->mAttribBuffers[index].divisor);
|
||||
return JS::Int32Value(mBoundVertexArray->mAttribs[index].divisor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -290,12 +292,12 @@ WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
|
||||
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED:
|
||||
{
|
||||
return JS::BooleanValue(mBoundVertexArray->mAttribBuffers[index].enabled);
|
||||
return JS::BooleanValue(mBoundVertexArray->mAttribs[index].enabled);
|
||||
}
|
||||
|
||||
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
|
||||
{
|
||||
return JS::BooleanValue(mBoundVertexArray->mAttribBuffers[index].normalized);
|
||||
return JS::BooleanValue(mBoundVertexArray->mAttribs[index].normalized);
|
||||
}
|
||||
|
||||
default:
|
||||
@ -321,7 +323,7 @@ WebGLContext::GetVertexAttribOffset(GLuint index, GLenum pname)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mBoundVertexArray->mAttribBuffers[index].byteOffset;
|
||||
return mBoundVertexArray->mAttribs[index].byteOffset;
|
||||
}
|
||||
|
||||
void
|
||||
@ -356,7 +358,7 @@ WebGLContext::VertexAttribPointer(GLuint index, GLint size, GLenum type,
|
||||
// requiredAlignment should always be a power of two.
|
||||
GLsizei requiredAlignmentMask = requiredAlignment - 1;
|
||||
|
||||
if ( !mBoundVertexArray->EnsureAttribIndex(index, "vertexAttribPointer") ) {
|
||||
if (!ValidateAttribIndex(index, "vertexAttribPointer")) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -387,7 +389,7 @@ WebGLContext::VertexAttribPointer(GLuint index, GLint size, GLenum type,
|
||||
return ErrorInvalidOperation("vertexAttribPointer: type must match bound VBO type: %d != %d", type, mBoundArrayBuffer->GLType());
|
||||
*/
|
||||
|
||||
WebGLVertexAttribData &vd = mBoundVertexArray->mAttribBuffers[index];
|
||||
WebGLVertexAttribData &vd = mBoundVertexArray->mAttribs[index];
|
||||
|
||||
vd.buf = mBoundArrayBuffer;
|
||||
vd.stride = stride;
|
||||
@ -409,11 +411,11 @@ WebGLContext::VertexAttribDivisor(GLuint index, GLuint divisor)
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if ( !mBoundVertexArray->EnsureAttribIndex(index, "vertexAttribDivisor") ) {
|
||||
if (!ValidateAttribIndex(index, "vertexAttribDivisor")) {
|
||||
return;
|
||||
}
|
||||
|
||||
WebGLVertexAttribData& vd = mBoundVertexArray->mAttribBuffers[index];
|
||||
WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[index];
|
||||
vd.divisor = divisor;
|
||||
|
||||
InvalidateBufferFetching();
|
||||
@ -498,7 +500,7 @@ bool WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcoun
|
||||
MakeContextCurrent();
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers()) {
|
||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
|
||||
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
|
||||
return false;
|
||||
}
|
||||
@ -655,7 +657,7 @@ WebGLContext::DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOff
|
||||
MakeContextCurrent();
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers()) {
|
||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
|
||||
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
|
||||
return false;
|
||||
}
|
||||
@ -756,10 +758,10 @@ WebGLContext::ValidateBufferFetching(const char *info)
|
||||
bool hasPerVertex = false;
|
||||
uint32_t maxVertices = UINT32_MAX;
|
||||
uint32_t maxInstances = UINT32_MAX;
|
||||
uint32_t attribs = mBoundVertexArray->mAttribBuffers.Length();
|
||||
uint32_t attribs = mBoundVertexArray->mAttribs.Length();
|
||||
|
||||
for (uint32_t i = 0; i < attribs; ++i) {
|
||||
const WebGLVertexAttribData& vd = mBoundVertexArray->mAttribBuffers[i];
|
||||
const WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[i];
|
||||
|
||||
// If the attrib array isn't enabled, there's nothing to check;
|
||||
// it's a static value.
|
||||
|
@ -51,11 +51,7 @@ WebGLFramebuffer::Attachment::HasAlpha() const {
|
||||
format = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).Format();
|
||||
else if (Renderbuffer())
|
||||
format = Renderbuffer()->InternalFormat();
|
||||
return format == LOCAL_GL_RGBA ||
|
||||
format == LOCAL_GL_LUMINANCE_ALPHA ||
|
||||
format == LOCAL_GL_ALPHA ||
|
||||
format == LOCAL_GL_RGBA4 ||
|
||||
format == LOCAL_GL_RGB5_A1;
|
||||
return FormatHasAlpha(format);
|
||||
}
|
||||
|
||||
void
|
||||
@ -67,8 +63,27 @@ WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture *tex, GLenum target, GLin
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::Attachment::HasUninitializedRenderbuffer() const {
|
||||
return mRenderbufferPtr && !mRenderbufferPtr->Initialized();
|
||||
WebGLFramebuffer::Attachment::HasUninitializedImageData() const {
|
||||
if (mRenderbufferPtr) {
|
||||
return mRenderbufferPtr->HasUninitializedImageData();
|
||||
} else if (mTexturePtr) {
|
||||
if (!mTexturePtr->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
|
||||
return false;
|
||||
return mTexturePtr->ImageInfoAt(mTexImageTarget, mTexImageLevel).HasUninitializedImageData();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::Attachment::SetImageDataStatus(WebGLImageDataStatus newStatus) {
|
||||
if (mRenderbufferPtr) {
|
||||
mRenderbufferPtr->SetImageDataStatus(newStatus);
|
||||
} else if (mTexturePtr) {
|
||||
mTexturePtr->SetImageDataStatus(mTexImageTarget, mTexImageLevel, newStatus);
|
||||
} else {
|
||||
MOZ_ASSERT(false); // should not get here, worth crashing a debug build.
|
||||
}
|
||||
}
|
||||
|
||||
const WebGLRectangleObject*
|
||||
@ -143,7 +158,7 @@ WebGLFramebuffer::Attachment::IsComplete() const {
|
||||
MOZ_CRASH("Invalid WebGL attachment poin?");
|
||||
}
|
||||
|
||||
NS_ABORT(); // should never get there
|
||||
MOZ_ASSERT(false); // should never get there
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -315,14 +330,14 @@ WebGLFramebuffer::GetAttachment(GLenum attachment) const {
|
||||
return mStencilAttachment;
|
||||
|
||||
if (!CheckColorAttachementNumber(attachment, "getAttachment")) {
|
||||
NS_ABORT();
|
||||
MOZ_ASSERT(false);
|
||||
return mColorAttachments[0];
|
||||
}
|
||||
|
||||
uint32_t colorAttachmentId = uint32_t(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
|
||||
|
||||
if (colorAttachmentId >= mColorAttachments.Length()) {
|
||||
NS_ABORT();
|
||||
MOZ_ASSERT(false);
|
||||
return mColorAttachments[0];
|
||||
}
|
||||
|
||||
@ -368,7 +383,7 @@ WebGLFramebuffer::DetachRenderbuffer(const WebGLRenderbuffer *rb) {
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::CheckAndInitializeRenderbuffers()
|
||||
WebGLFramebuffer::CheckAndInitializeAttachments()
|
||||
{
|
||||
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
||||
// enforce WebGL section 6.5 which is WebGL-specific, hence OpenGL itself would not
|
||||
@ -387,16 +402,16 @@ WebGLFramebuffer::CheckAndInitializeRenderbuffers()
|
||||
size_t colorAttachmentCount = size_t(mColorAttachments.Length());
|
||||
|
||||
{
|
||||
bool hasUnitializedRenderbuffers = false;
|
||||
bool hasUnitializedAttachments = false;
|
||||
|
||||
for (size_t i = 0; i < colorAttachmentCount; i++) {
|
||||
hasUnitializedRenderbuffers |= mColorAttachments[i].HasUninitializedRenderbuffer();
|
||||
hasUnitializedAttachments |= mColorAttachments[i].HasUninitializedImageData();
|
||||
}
|
||||
|
||||
if (!hasUnitializedRenderbuffers &&
|
||||
!mDepthAttachment.HasUninitializedRenderbuffer() &&
|
||||
!mStencilAttachment.HasUninitializedRenderbuffer() &&
|
||||
!mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
if (!hasUnitializedAttachments &&
|
||||
!mDepthAttachment.HasUninitializedImageData() &&
|
||||
!mStencilAttachment.HasUninitializedImageData() &&
|
||||
!mDepthStencilAttachment.HasUninitializedImageData())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -420,21 +435,21 @@ WebGLFramebuffer::CheckAndInitializeRenderbuffers()
|
||||
|
||||
for (size_t i = 0; i < colorAttachmentCount; i++)
|
||||
{
|
||||
colorAttachmentsMask[i] = mColorAttachments[i].HasUninitializedRenderbuffer();
|
||||
colorAttachmentsMask[i] = mColorAttachments[i].HasUninitializedImageData();
|
||||
|
||||
if (colorAttachmentsMask[i]) {
|
||||
mask |= LOCAL_GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (mDepthAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
if (mDepthAttachment.HasUninitializedImageData() ||
|
||||
mDepthStencilAttachment.HasUninitializedImageData())
|
||||
{
|
||||
mask |= LOCAL_GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
|
||||
if (mStencilAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
if (mStencilAttachment.HasUninitializedImageData() ||
|
||||
mDepthStencilAttachment.HasUninitializedImageData())
|
||||
{
|
||||
mask |= LOCAL_GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
@ -443,19 +458,16 @@ WebGLFramebuffer::CheckAndInitializeRenderbuffers()
|
||||
|
||||
for (size_t i = 0; i < colorAttachmentCount; i++)
|
||||
{
|
||||
if (colorAttachmentsMask[i]) {
|
||||
mColorAttachments[i].Renderbuffer()->SetInitialized(true);
|
||||
}
|
||||
if (mColorAttachments[i].HasUninitializedImageData())
|
||||
mColorAttachments[i].SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
|
||||
}
|
||||
|
||||
if (mDepthAttachment.HasUninitializedRenderbuffer())
|
||||
mDepthAttachment.Renderbuffer()->SetInitialized(true);
|
||||
|
||||
if (mStencilAttachment.HasUninitializedRenderbuffer())
|
||||
mStencilAttachment.Renderbuffer()->SetInitialized(true);
|
||||
|
||||
if (mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
mDepthStencilAttachment.Renderbuffer()->SetInitialized(true);
|
||||
if (mDepthAttachment.HasUninitializedImageData())
|
||||
mDepthAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
|
||||
if (mStencilAttachment.HasUninitializedImageData())
|
||||
mStencilAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
|
||||
if (mDepthStencilAttachment.HasUninitializedImageData())
|
||||
mDepthStencilAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -545,14 +557,11 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
||||
aName, aFlags);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_7(WebGLFramebuffer,
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_4(WebGLFramebuffer,
|
||||
mColorAttachments,
|
||||
mDepthAttachment.mTexturePtr,
|
||||
mDepthAttachment.mRenderbufferPtr,
|
||||
mStencilAttachment.mTexturePtr,
|
||||
mStencilAttachment.mRenderbufferPtr,
|
||||
mDepthStencilAttachment.mTexturePtr,
|
||||
mDepthStencilAttachment.mRenderbufferPtr)
|
||||
mDepthAttachment,
|
||||
mStencilAttachment,
|
||||
mDepthStencilAttachment)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLFramebuffer, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLFramebuffer, Release)
|
||||
|
@ -78,7 +78,8 @@ public:
|
||||
return mTexImageLevel;
|
||||
}
|
||||
|
||||
bool HasUninitializedRenderbuffer() const;
|
||||
bool HasUninitializedImageData() const;
|
||||
void SetImageDataStatus(WebGLImageDataStatus x);
|
||||
|
||||
void Reset() {
|
||||
mTexturePtr = nullptr;
|
||||
@ -161,7 +162,7 @@ public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebuffer)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLFramebuffer)
|
||||
|
||||
bool CheckAndInitializeRenderbuffers();
|
||||
bool CheckAndInitializeAttachments();
|
||||
|
||||
bool CheckColorAttachementNumber(GLenum attachment, const char * functionName) const;
|
||||
|
||||
|
@ -102,8 +102,8 @@ public:
|
||||
{ }
|
||||
|
||||
~WebGLRefCountedObject() {
|
||||
NS_ABORT_IF_FALSE(mWebGLRefCnt == 0, "destroying WebGL object still referenced by other WebGL objects");
|
||||
NS_ABORT_IF_FALSE(mDeletionStatus == Deleted, "Derived class destructor must call DeleteOnce()");
|
||||
MOZ_ASSERT(mWebGLRefCnt == 0, "destroying WebGL object still referenced by other WebGL objects");
|
||||
MOZ_ASSERT(mDeletionStatus == Deleted, "Derived class destructor must call DeleteOnce()");
|
||||
}
|
||||
|
||||
// called by WebGLRefPtr
|
||||
@ -113,7 +113,7 @@ public:
|
||||
|
||||
// called by WebGLRefPtr
|
||||
void WebGLRelease() {
|
||||
NS_ABORT_IF_FALSE(mWebGLRefCnt > 0, "releasing WebGL object with WebGL refcnt already zero");
|
||||
MOZ_ASSERT(mWebGLRefCnt > 0, "releasing WebGL object with WebGL refcnt already zero");
|
||||
--mWebGLRefCnt;
|
||||
MaybeDelete();
|
||||
}
|
||||
@ -215,12 +215,12 @@ public:
|
||||
}
|
||||
|
||||
T* operator->() const {
|
||||
NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a nullptr WebGLRefPtr with operator->()!");
|
||||
MOZ_ASSERT(mRawPtr != 0, "You can't dereference a nullptr WebGLRefPtr with operator->()!");
|
||||
return get();
|
||||
}
|
||||
|
||||
T& operator*() const {
|
||||
NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a nullptr WebGLRefPtr with operator*()!");
|
||||
MOZ_ASSERT(mRawPtr != 0, "You can't dereference a nullptr WebGLRefPtr with operator*()!");
|
||||
return *get();
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext *context)
|
||||
, mInternalFormat(0)
|
||||
, mInternalFormatForGL(0)
|
||||
, mHasEverBeenBound(false)
|
||||
, mInitialized(false)
|
||||
, mImageDataStatus(WebGLImageDataStatus::NoImageData)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
mContext->MakeContextCurrent();
|
||||
|
@ -33,8 +33,13 @@ public:
|
||||
bool HasEverBeenBound() { return mHasEverBeenBound; }
|
||||
void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
|
||||
|
||||
bool Initialized() const { return mInitialized; }
|
||||
void SetInitialized(bool aInitialized) { mInitialized = aInitialized; }
|
||||
bool HasUninitializedImageData() const { return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData; }
|
||||
void SetImageDataStatus(WebGLImageDataStatus x) {
|
||||
// there is no way to go from having image data to not having any
|
||||
MOZ_ASSERT(x != WebGLImageDataStatus::NoImageData ||
|
||||
mImageDataStatus == WebGLImageDataStatus::NoImageData);
|
||||
mImageDataStatus = x;
|
||||
}
|
||||
|
||||
GLenum InternalFormat() const { return mInternalFormat; }
|
||||
void SetInternalFormat(GLenum aInternalFormat) { mInternalFormat = aInternalFormat; }
|
||||
@ -66,7 +71,7 @@ protected:
|
||||
GLenum mInternalFormat;
|
||||
GLenum mInternalFormatForGL;
|
||||
bool mHasEverBeenBound;
|
||||
bool mInitialized;
|
||||
WebGLImageDataStatus mImageDataStatus;
|
||||
|
||||
friend class WebGLFramebuffer;
|
||||
};
|
||||
|
@ -37,30 +37,30 @@ class WebGLImageConverter
|
||||
* texels with typed pointers and this value will tell us by how much we need
|
||||
* to increment these pointers to advance to the next texel.
|
||||
*/
|
||||
template<int Format>
|
||||
template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format>
|
||||
static size_t NumElementsPerTexelForFormat() {
|
||||
switch (Format) {
|
||||
case R8:
|
||||
case A8:
|
||||
case R32F:
|
||||
case A32F:
|
||||
case RGBA5551:
|
||||
case RGBA4444:
|
||||
case RGB565:
|
||||
case WebGLTexelFormat::R8:
|
||||
case WebGLTexelFormat::A8:
|
||||
case WebGLTexelFormat::R32F:
|
||||
case WebGLTexelFormat::A32F:
|
||||
case WebGLTexelFormat::RGBA5551:
|
||||
case WebGLTexelFormat::RGBA4444:
|
||||
case WebGLTexelFormat::RGB565:
|
||||
return 1;
|
||||
case RA8:
|
||||
case RA32F:
|
||||
case WebGLTexelFormat::RA8:
|
||||
case WebGLTexelFormat::RA32F:
|
||||
return 2;
|
||||
case RGB8:
|
||||
case RGB32F:
|
||||
case WebGLTexelFormat::RGB8:
|
||||
case WebGLTexelFormat::RGB32F:
|
||||
return 3;
|
||||
case RGBA8:
|
||||
case BGRA8:
|
||||
case BGRX8:
|
||||
case RGBA32F:
|
||||
case WebGLTexelFormat::RGBA8:
|
||||
case WebGLTexelFormat::BGRA8:
|
||||
case WebGLTexelFormat::BGRX8:
|
||||
case WebGLTexelFormat::RGBA32F:
|
||||
return 4;
|
||||
default:
|
||||
NS_ABORT_IF_FALSE(false, "Unknown texel format. Coding mistake?");
|
||||
MOZ_ASSERT(false, "Unknown texel format. Coding mistake?");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -73,9 +73,9 @@ class WebGLImageConverter
|
||||
* to return immediately in these cases to allow the compiler to avoid generating
|
||||
* useless code.
|
||||
*/
|
||||
template<WebGLTexelFormat SrcFormat,
|
||||
WebGLTexelFormat DstFormat,
|
||||
WebGLTexelPremultiplicationOp PremultiplicationOp>
|
||||
template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) SrcFormat,
|
||||
MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) DstFormat,
|
||||
MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelPremultiplicationOp) PremultiplicationOp>
|
||||
void run()
|
||||
{
|
||||
// check for never-called cases. We early-return to allow the compiler
|
||||
@ -86,7 +86,7 @@ class WebGLImageConverter
|
||||
// must check that and abort in that case. See WebGLContext::ConvertImage.
|
||||
|
||||
if (SrcFormat == DstFormat &&
|
||||
PremultiplicationOp == NoPremultiplicationOp)
|
||||
PremultiplicationOp == WebGLTexelPremultiplicationOp::None)
|
||||
{
|
||||
// Should have used a fast exit path earlier, rather than entering this function.
|
||||
// we explicitly return here to allow the compiler to avoid generating this code
|
||||
@ -98,11 +98,11 @@ class WebGLImageConverter
|
||||
// ImageData is always RGBA8. So all other SrcFormat will always satisfy DstFormat==SrcFormat,
|
||||
// so we can avoid compiling the code for all the unreachable paths.
|
||||
const bool CanSrcFormatComeFromDOMElementOrImageData
|
||||
= SrcFormat == BGRA8 ||
|
||||
SrcFormat == BGRX8 ||
|
||||
SrcFormat == A8 ||
|
||||
SrcFormat == RGB565 ||
|
||||
SrcFormat == RGBA8;
|
||||
= SrcFormat == WebGLTexelFormat::BGRA8 ||
|
||||
SrcFormat == WebGLTexelFormat::BGRX8 ||
|
||||
SrcFormat == WebGLTexelFormat::A8 ||
|
||||
SrcFormat == WebGLTexelFormat::RGB565 ||
|
||||
SrcFormat == WebGLTexelFormat::RGBA8;
|
||||
if (!CanSrcFormatComeFromDOMElementOrImageData &&
|
||||
SrcFormat != DstFormat)
|
||||
{
|
||||
@ -111,7 +111,7 @@ class WebGLImageConverter
|
||||
|
||||
// Likewise, only textures uploaded from DOM elements or ImageData can possibly have to be unpremultiplied.
|
||||
if (!CanSrcFormatComeFromDOMElementOrImageData &&
|
||||
PremultiplicationOp == Unpremultiply)
|
||||
PremultiplicationOp == WebGLTexelPremultiplicationOp::Unpremultiply)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -126,7 +126,7 @@ class WebGLImageConverter
|
||||
!HasColor(DstFormat))
|
||||
{
|
||||
|
||||
if (PremultiplicationOp != NoPremultiplicationOp)
|
||||
if (PremultiplicationOp != WebGLTexelPremultiplicationOp::None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -134,7 +134,7 @@ class WebGLImageConverter
|
||||
|
||||
// end of early return cases.
|
||||
|
||||
NS_ABORT_IF_FALSE(!mAlreadyRun, "converter should be run only once!");
|
||||
MOZ_ASSERT(!mAlreadyRun, "converter should be run only once!");
|
||||
mAlreadyRun = true;
|
||||
|
||||
// gather some compile-time meta-data about the formats at hand.
|
||||
@ -146,9 +146,9 @@ class WebGLImageConverter
|
||||
typename DataTypeForFormat<DstFormat>::Type
|
||||
DstType;
|
||||
|
||||
const int IntermediateSrcFormat
|
||||
const MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) IntermediateSrcFormat
|
||||
= IntermediateFormat<SrcFormat>::Value;
|
||||
const int IntermediateDstFormat
|
||||
const MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) IntermediateDstFormat
|
||||
= IntermediateFormat<DstFormat>::Value;
|
||||
typedef
|
||||
typename DataTypeForFormat<IntermediateSrcFormat>::Type
|
||||
@ -160,8 +160,8 @@ class WebGLImageConverter
|
||||
const size_t NumElementsPerSrcTexel = NumElementsPerTexelForFormat<SrcFormat>();
|
||||
const size_t NumElementsPerDstTexel = NumElementsPerTexelForFormat<DstFormat>();
|
||||
const size_t MaxElementsPerTexel = 4;
|
||||
NS_ABORT_IF_FALSE(NumElementsPerSrcTexel <= MaxElementsPerTexel, "unhandled format");
|
||||
NS_ABORT_IF_FALSE(NumElementsPerDstTexel <= MaxElementsPerTexel, "unhandled format");
|
||||
MOZ_ASSERT(NumElementsPerSrcTexel <= MaxElementsPerTexel, "unhandled format");
|
||||
MOZ_ASSERT(NumElementsPerDstTexel <= MaxElementsPerTexel, "unhandled format");
|
||||
|
||||
// we assume that the strides are multiples of the sizeof of respective types.
|
||||
// this assumption will allow us to iterate over src and dst images using typed
|
||||
@ -169,9 +169,9 @@ class WebGLImageConverter
|
||||
// So this assumption allows us to write cleaner and safer code, but it might
|
||||
// not be true forever and if it eventually becomes wrong, we'll have to revert
|
||||
// to always iterating using uint8_t* pointers regardless of the types at hand.
|
||||
NS_ABORT_IF_FALSE(mSrcStride % sizeof(SrcType) == 0 &&
|
||||
mDstStride % sizeof(DstType) == 0,
|
||||
"Unsupported: texture stride is not a multiple of sizeof(type)");
|
||||
MOZ_ASSERT(mSrcStride % sizeof(SrcType) == 0 &&
|
||||
mDstStride % sizeof(DstType) == 0,
|
||||
"Unsupported: texture stride is not a multiple of sizeof(type)");
|
||||
const ptrdiff_t srcStrideInElements = mSrcStride / sizeof(SrcType);
|
||||
const ptrdiff_t dstStrideInElements = mDstStride / sizeof(DstType);
|
||||
|
||||
@ -213,7 +213,8 @@ class WebGLImageConverter
|
||||
return;
|
||||
}
|
||||
|
||||
template<WebGLTexelFormat SrcFormat, WebGLTexelFormat DstFormat>
|
||||
template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) SrcFormat,
|
||||
MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) DstFormat>
|
||||
void run(WebGLTexelPremultiplicationOp premultiplicationOp)
|
||||
{
|
||||
#define WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(PremultiplicationOp) \
|
||||
@ -221,17 +222,17 @@ class WebGLImageConverter
|
||||
return run<SrcFormat, DstFormat, PremultiplicationOp>();
|
||||
|
||||
switch (premultiplicationOp) {
|
||||
WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(NoPremultiplicationOp)
|
||||
WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(Premultiply)
|
||||
WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(Unpremultiply)
|
||||
WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(WebGLTexelPremultiplicationOp::None)
|
||||
WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(WebGLTexelPremultiplicationOp::Premultiply)
|
||||
WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(WebGLTexelPremultiplicationOp::Unpremultiply)
|
||||
default:
|
||||
NS_ABORT_IF_FALSE(false, "unhandled case. Coding mistake?");
|
||||
MOZ_ASSERT(false, "unhandled case. Coding mistake?");
|
||||
}
|
||||
|
||||
#undef WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP
|
||||
}
|
||||
|
||||
template<WebGLTexelFormat SrcFormat>
|
||||
template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) SrcFormat>
|
||||
void run(WebGLTexelFormat dstFormat,
|
||||
WebGLTexelPremultiplicationOp premultiplicationOp)
|
||||
{
|
||||
@ -240,21 +241,21 @@ class WebGLImageConverter
|
||||
return run<SrcFormat, DstFormat>(premultiplicationOp);
|
||||
|
||||
switch (dstFormat) {
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(R8)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(A8)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(R32F)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(A32F)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RA8)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RA32F)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGB8)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGB565)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGB32F)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGBA8)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGBA5551)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGBA4444)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGBA32F)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R8)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A8)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R32F)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A32F)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA8)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA32F)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB8)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB565)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB32F)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA8)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA5551)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA4444)
|
||||
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA32F)
|
||||
default:
|
||||
NS_ABORT_IF_FALSE(false, "unhandled case. Coding mistake?");
|
||||
MOZ_ASSERT(false, "unhandled case. Coding mistake?");
|
||||
}
|
||||
|
||||
#undef WEBGLIMAGECONVERTER_CASE_DSTFORMAT
|
||||
@ -271,23 +272,23 @@ public:
|
||||
return run<SrcFormat>(dstFormat, premultiplicationOp);
|
||||
|
||||
switch (srcFormat) {
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(R8)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(A8)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(R32F)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(A32F)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RA8)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RA32F)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGB8)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(BGRX8) // source format only
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGB565)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGB32F)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGBA8)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(BGRA8)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGBA5551)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGBA4444)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGBA32F)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R8)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A8)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R32F)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A32F)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA8)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA32F)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB8)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::BGRX8) // source format only
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB565)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB32F)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA8)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::BGRA8)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA5551)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA4444)
|
||||
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA32F)
|
||||
default:
|
||||
NS_ABORT_IF_FALSE(false, "unhandled case. Coding mistake?");
|
||||
MOZ_ASSERT(false, "unhandled case. Coding mistake?");
|
||||
}
|
||||
|
||||
#undef WEBGLIMAGECONVERTER_CASE_SRCFORMAT
|
||||
@ -335,7 +336,7 @@ WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t
|
||||
// So the case we're handling here is when even though no format conversion is needed,
|
||||
// we still might have to flip vertically and/or to adjust to a different stride.
|
||||
|
||||
NS_ABORT_IF_FALSE(mPixelStoreFlipY || srcStride != dstStride, "Performance trap -- should handle this case earlier, to avoid memcpy");
|
||||
MOZ_ASSERT(mPixelStoreFlipY || srcStride != dstStride, "Performance trap -- should handle this case earlier, to avoid memcpy");
|
||||
|
||||
size_t row_size = width * dstTexelSize; // doesn't matter, src and dst formats agree
|
||||
const uint8_t* ptr = src;
|
||||
@ -365,10 +366,10 @@ WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t
|
||||
WebGLImageConverter converter(width, height, src, dstStart, srcStride, signedDstStride);
|
||||
|
||||
const WebGLTexelPremultiplicationOp premultiplicationOp
|
||||
= FormatsRequireNoPremultiplicationOp ? NoPremultiplicationOp
|
||||
: (!srcPremultiplied && dstPremultiplied) ? Premultiply
|
||||
: (srcPremultiplied && !dstPremultiplied) ? Unpremultiply
|
||||
: NoPremultiplicationOp;
|
||||
= FormatsRequireNoPremultiplicationOp ? WebGLTexelPremultiplicationOp::None
|
||||
: (!srcPremultiplied && dstPremultiplied) ? WebGLTexelPremultiplicationOp::Premultiply
|
||||
: (srcPremultiplied && !dstPremultiplied) ? WebGLTexelPremultiplicationOp::Unpremultiply
|
||||
: WebGLTexelPremultiplicationOp::None;
|
||||
|
||||
converter.run(srcFormat, dstFormat, premultiplicationOp);
|
||||
|
||||
|
@ -34,47 +34,46 @@
|
||||
|
||||
#include "WebGLTypes.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined _MSC_VER
|
||||
#define FORCE_INLINE __forceinline
|
||||
#elif defined __GNUC__
|
||||
#define FORCE_INLINE __attribute__((always_inline)) inline
|
||||
#else
|
||||
#define FORCE_INLINE inline
|
||||
#endif
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace WebGLTexelConversions {
|
||||
|
||||
enum WebGLTexelPremultiplicationOp
|
||||
{
|
||||
NoPremultiplicationOp,
|
||||
MOZ_BEGIN_ENUM_CLASS(WebGLTexelPremultiplicationOp, int)
|
||||
None,
|
||||
Premultiply,
|
||||
Unpremultiply
|
||||
};
|
||||
MOZ_END_ENUM_CLASS(WebGLTexelPremultiplicationOp)
|
||||
|
||||
template<int Format>
|
||||
namespace WebGLTexelConversions {
|
||||
|
||||
// remove this as soon as B2G and Windows use newer compilers
|
||||
#ifdef MOZ_HAVE_CXX11_STRONG_ENUMS
|
||||
#define MOZ_ENUM_CLASS_INTEGER_TYPE(X) X
|
||||
#else
|
||||
#define MOZ_ENUM_CLASS_INTEGER_TYPE(X) X::Enum
|
||||
#endif
|
||||
|
||||
template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format>
|
||||
struct IsFloatFormat
|
||||
{
|
||||
static const bool Value =
|
||||
Format == RGBA32F ||
|
||||
Format == RGB32F ||
|
||||
Format == RA32F ||
|
||||
Format == R32F ||
|
||||
Format == A32F;
|
||||
Format == WebGLTexelFormat::RGBA32F ||
|
||||
Format == WebGLTexelFormat::RGB32F ||
|
||||
Format == WebGLTexelFormat::RA32F ||
|
||||
Format == WebGLTexelFormat::R32F ||
|
||||
Format == WebGLTexelFormat::A32F;
|
||||
};
|
||||
|
||||
template<int Format>
|
||||
template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format>
|
||||
struct Is16bppFormat
|
||||
{
|
||||
static const bool Value =
|
||||
Format == RGBA4444 ||
|
||||
Format == RGBA5551 ||
|
||||
Format == RGB565;
|
||||
Format == WebGLTexelFormat::RGBA4444 ||
|
||||
Format == WebGLTexelFormat::RGBA5551 ||
|
||||
Format == WebGLTexelFormat::RGB565;
|
||||
};
|
||||
|
||||
template<int Format,
|
||||
template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format,
|
||||
bool IsFloat = IsFloatFormat<Format>::Value,
|
||||
bool Is16bpp = Is16bppFormat<Format>::Value>
|
||||
struct DataTypeForFormat
|
||||
@ -82,83 +81,86 @@ struct DataTypeForFormat
|
||||
typedef uint8_t Type;
|
||||
};
|
||||
|
||||
template<int Format>
|
||||
template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format>
|
||||
struct DataTypeForFormat<Format, true, false>
|
||||
{
|
||||
typedef float Type;
|
||||
};
|
||||
|
||||
template<int Format>
|
||||
template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format>
|
||||
struct DataTypeForFormat<Format, false, true>
|
||||
{
|
||||
typedef uint16_t Type;
|
||||
};
|
||||
|
||||
template<int Format>
|
||||
template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format>
|
||||
struct IntermediateFormat
|
||||
{
|
||||
static const int Value = IsFloatFormat<Format>::Value ? RGBA32F : RGBA8;
|
||||
static const MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Value
|
||||
= IsFloatFormat<Format>::Value
|
||||
? WebGLTexelFormat::RGBA32F
|
||||
: WebGLTexelFormat::RGBA8;
|
||||
};
|
||||
|
||||
inline size_t TexelBytesForFormat(int format) {
|
||||
inline size_t TexelBytesForFormat(WebGLTexelFormat format) {
|
||||
switch (format) {
|
||||
case WebGLTexelConversions::R8:
|
||||
case WebGLTexelConversions::A8:
|
||||
case WebGLTexelFormat::R8:
|
||||
case WebGLTexelFormat::A8:
|
||||
return 1;
|
||||
case WebGLTexelConversions::RA8:
|
||||
case WebGLTexelConversions::RGBA5551:
|
||||
case WebGLTexelConversions::RGBA4444:
|
||||
case WebGLTexelConversions::RGB565:
|
||||
case WebGLTexelConversions::D16:
|
||||
case WebGLTexelFormat::RA8:
|
||||
case WebGLTexelFormat::RGBA5551:
|
||||
case WebGLTexelFormat::RGBA4444:
|
||||
case WebGLTexelFormat::RGB565:
|
||||
case WebGLTexelFormat::D16:
|
||||
return 2;
|
||||
case WebGLTexelConversions::RGB8:
|
||||
case WebGLTexelFormat::RGB8:
|
||||
return 3;
|
||||
case WebGLTexelConversions::RGBA8:
|
||||
case WebGLTexelConversions::BGRA8:
|
||||
case WebGLTexelConversions::BGRX8:
|
||||
case WebGLTexelConversions::R32F:
|
||||
case WebGLTexelConversions::A32F:
|
||||
case WebGLTexelConversions::D32:
|
||||
case WebGLTexelConversions::D24S8:
|
||||
case WebGLTexelFormat::RGBA8:
|
||||
case WebGLTexelFormat::BGRA8:
|
||||
case WebGLTexelFormat::BGRX8:
|
||||
case WebGLTexelFormat::R32F:
|
||||
case WebGLTexelFormat::A32F:
|
||||
case WebGLTexelFormat::D32:
|
||||
case WebGLTexelFormat::D24S8:
|
||||
return 4;
|
||||
case WebGLTexelConversions::RA32F:
|
||||
case WebGLTexelFormat::RA32F:
|
||||
return 8;
|
||||
case WebGLTexelConversions::RGB32F:
|
||||
case WebGLTexelFormat::RGB32F:
|
||||
return 12;
|
||||
case WebGLTexelConversions::RGBA32F:
|
||||
case WebGLTexelFormat::RGBA32F:
|
||||
return 16;
|
||||
default:
|
||||
NS_ABORT_IF_FALSE(false, "Unknown texel format. Coding mistake?");
|
||||
MOZ_ASSERT(false, "Unknown texel format. Coding mistake?");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE bool HasAlpha(int format) {
|
||||
return format == A8 ||
|
||||
format == A32F ||
|
||||
format == RA8 ||
|
||||
format == RA32F ||
|
||||
format == RGBA8 ||
|
||||
format == BGRA8 ||
|
||||
format == RGBA32F ||
|
||||
format == RGBA4444 ||
|
||||
format == RGBA5551;
|
||||
MOZ_ALWAYS_INLINE bool HasAlpha(WebGLTexelFormat format) {
|
||||
return format == WebGLTexelFormat::A8 ||
|
||||
format == WebGLTexelFormat::A32F ||
|
||||
format == WebGLTexelFormat::RA8 ||
|
||||
format == WebGLTexelFormat::RA32F ||
|
||||
format == WebGLTexelFormat::RGBA8 ||
|
||||
format == WebGLTexelFormat::BGRA8 ||
|
||||
format == WebGLTexelFormat::RGBA32F ||
|
||||
format == WebGLTexelFormat::RGBA4444 ||
|
||||
format == WebGLTexelFormat::RGBA5551;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool HasColor(int format) {
|
||||
return format == R8 ||
|
||||
format == R32F ||
|
||||
format == RA8 ||
|
||||
format == RA32F ||
|
||||
format == RGB8 ||
|
||||
format == BGRX8 ||
|
||||
format == RGB565 ||
|
||||
format == RGB32F ||
|
||||
format == RGBA8 ||
|
||||
format == BGRA8 ||
|
||||
format == RGBA32F ||
|
||||
format == RGBA4444 ||
|
||||
format == RGBA5551;
|
||||
MOZ_ALWAYS_INLINE bool HasColor(WebGLTexelFormat format) {
|
||||
return format == WebGLTexelFormat::R8 ||
|
||||
format == WebGLTexelFormat::R32F ||
|
||||
format == WebGLTexelFormat::RA8 ||
|
||||
format == WebGLTexelFormat::RA32F ||
|
||||
format == WebGLTexelFormat::RGB8 ||
|
||||
format == WebGLTexelFormat::BGRX8 ||
|
||||
format == WebGLTexelFormat::RGB565 ||
|
||||
format == WebGLTexelFormat::RGB32F ||
|
||||
format == WebGLTexelFormat::RGBA8 ||
|
||||
format == WebGLTexelFormat::BGRA8 ||
|
||||
format == WebGLTexelFormat::RGBA32F ||
|
||||
format == WebGLTexelFormat::RGBA4444 ||
|
||||
format == WebGLTexelFormat::RGBA5551;
|
||||
}
|
||||
|
||||
|
||||
@ -170,16 +172,16 @@ FORCE_INLINE bool HasColor(int format) {
|
||||
//----------------------------------------------------------------------
|
||||
// Pixel unpacking routines.
|
||||
|
||||
template<int Format, typename SrcType, typename DstType>
|
||||
FORCE_INLINE void
|
||||
template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format, typename SrcType, typename DstType>
|
||||
MOZ_ALWAYS_INLINE void
|
||||
unpack(const SrcType* __restrict src,
|
||||
DstType* __restrict dst)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(false, "Unimplemented texture format conversion");
|
||||
MOZ_ASSERT(false, "Unimplemented texture format conversion");
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<RGBA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::RGBA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
@ -187,8 +189,8 @@ unpack<RGBA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restri
|
||||
dst[3] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<RGB8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::RGB8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
@ -196,8 +198,8 @@ unpack<RGB8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restric
|
||||
dst[3] = 0xFF;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<BGRA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::BGRA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[2];
|
||||
dst[1] = src[1];
|
||||
@ -205,8 +207,8 @@ unpack<BGRA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restri
|
||||
dst[3] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<BGRX8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::BGRX8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[2];
|
||||
dst[1] = src[1];
|
||||
@ -214,8 +216,8 @@ unpack<BGRX8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restri
|
||||
dst[3] = 0xFF;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<RGBA5551, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::RGBA5551, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
uint16_t packedValue = src[0];
|
||||
uint8_t r = (packedValue >> 11) & 0x1F;
|
||||
@ -227,8 +229,8 @@ unpack<RGBA5551, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __r
|
||||
dst[3] = (packedValue & 0x1) ? 0xFF : 0;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<RGBA4444, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::RGBA4444, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
uint16_t packedValue = src[0];
|
||||
uint8_t r = (packedValue >> 12) & 0x0F;
|
||||
@ -241,8 +243,8 @@ unpack<RGBA4444, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __r
|
||||
dst[3] = (a << 4) | a;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<RGB565, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::RGB565, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
uint16_t packedValue = src[0];
|
||||
uint8_t r = (packedValue >> 11) & 0x1F;
|
||||
@ -254,8 +256,8 @@ unpack<RGB565, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __res
|
||||
dst[3] = 0xFF;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<R8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::R8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[0];
|
||||
@ -263,8 +265,8 @@ unpack<R8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict
|
||||
dst[3] = 0xFF;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<RA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::RA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[0];
|
||||
@ -272,8 +274,8 @@ unpack<RA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict
|
||||
dst[3] = src[1];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<A8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::A8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = 0;
|
||||
dst[1] = 0;
|
||||
@ -281,8 +283,8 @@ unpack<A8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict
|
||||
dst[3] = src[0];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<RGBA32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::RGBA32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
@ -290,8 +292,8 @@ unpack<RGBA32F, float, float>(const float* __restrict src, float* __restrict dst
|
||||
dst[3] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<RGB32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::RGB32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
@ -299,8 +301,8 @@ unpack<RGB32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
dst[3] = 1.0f;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<R32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::R32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[0];
|
||||
@ -308,8 +310,8 @@ unpack<R32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
dst[3] = 1.0f;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<RA32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::RA32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[0];
|
||||
@ -317,8 +319,8 @@ unpack<RA32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
dst[3] = src[1];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
unpack<A32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
unpack<WebGLTexelFormat::A32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
dst[0] = 0;
|
||||
dst[1] = 0;
|
||||
@ -330,63 +332,66 @@ unpack<A32F, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
// Pixel packing routines.
|
||||
//
|
||||
|
||||
template<int Format, int PremultiplicationOp, typename SrcType, typename DstType>
|
||||
FORCE_INLINE void
|
||||
template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format,
|
||||
MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelPremultiplicationOp) PremultiplicationOp,
|
||||
typename SrcType,
|
||||
typename DstType>
|
||||
MOZ_ALWAYS_INLINE void
|
||||
pack(const SrcType* __restrict src,
|
||||
DstType* __restrict dst)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(false, "Unimplemented texture format conversion");
|
||||
MOZ_ASSERT(false, "Unimplemented texture format conversion");
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<A8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::A8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<A8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::A8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<A8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::A8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<R8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::R8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<R8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::R8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] / 255.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
dst[0] = srcR;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<R8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::R8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
dst[0] = srcR;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RA8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RA8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RA8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RA8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] / 255.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
@ -395,8 +400,8 @@ pack<RA8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t*
|
||||
}
|
||||
|
||||
// FIXME: this routine is lossy and must be removed.
|
||||
template<> FORCE_INLINE void
|
||||
pack<RA8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RA8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
@ -404,16 +409,16 @@ pack<RA8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_
|
||||
dst[1] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGB8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGB8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] / 255.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
@ -424,8 +429,8 @@ pack<RGB8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t
|
||||
dst[2] = srcB;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGB8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
@ -436,8 +441,8 @@ pack<RGB8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8
|
||||
dst[2] = srcB;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGBA8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGBA8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
@ -445,8 +450,8 @@ pack<RGBA8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict s
|
||||
dst[3] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGBA8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGBA8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] / 255.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
@ -459,8 +464,8 @@ pack<RGBA8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_
|
||||
}
|
||||
|
||||
// FIXME: this routine is lossy and must be removed.
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGBA8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGBA8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
@ -472,8 +477,8 @@ pack<RGBA8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint
|
||||
dst[3] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGBA4444, NoPremultiplicationOp, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::None, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
{
|
||||
*dst = ( ((src[0] & 0xF0) << 8)
|
||||
| ((src[1] & 0xF0) << 4)
|
||||
@ -481,8 +486,8 @@ pack<RGBA4444, NoPremultiplicationOp, uint8_t, uint16_t>(const uint8_t* __restri
|
||||
| (src[3] >> 4) );
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGBA4444, Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] / 255.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
@ -495,8 +500,8 @@ pack<RGBA4444, Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, ui
|
||||
}
|
||||
|
||||
// FIXME: this routine is lossy and must be removed.
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGBA4444, Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
@ -508,8 +513,8 @@ pack<RGBA4444, Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src,
|
||||
| (src[3] >> 4));
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGBA5551, NoPremultiplicationOp, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::None, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
{
|
||||
*dst = ( ((src[0] & 0xF8) << 8)
|
||||
| ((src[1] & 0xF8) << 3)
|
||||
@ -517,8 +522,8 @@ pack<RGBA5551, NoPremultiplicationOp, uint8_t, uint16_t>(const uint8_t* __restri
|
||||
| (src[3] >> 7));
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGBA5551, Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] / 255.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
@ -531,8 +536,8 @@ pack<RGBA5551, Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, ui
|
||||
}
|
||||
|
||||
// FIXME: this routine is lossy and must be removed.
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGBA5551, Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
@ -544,16 +549,16 @@ pack<RGBA5551, Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src,
|
||||
| (src[3] >> 7));
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGB565, NoPremultiplicationOp, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::None, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
{
|
||||
*dst = ( ((src[0] & 0xF8) << 8)
|
||||
| ((src[1] & 0xFC) << 3)
|
||||
| ((src[2] & 0xF8) >> 3));
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGB565, Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] / 255.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
@ -565,8 +570,8 @@ pack<RGB565, Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint
|
||||
}
|
||||
|
||||
// FIXME: this routine is lossy and must be removed.
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGB565, Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
|
||||
uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
|
||||
@ -577,16 +582,16 @@ pack<RGB565, Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, ui
|
||||
| ((srcB & 0xF8) >> 3));
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGB32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGB32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGB32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGB32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3];
|
||||
dst[0] = src[0] * scaleFactor;
|
||||
@ -594,8 +599,8 @@ pack<RGB32F, Premultiply, float, float>(const float* __restrict src, float* __re
|
||||
dst[2] = src[2] * scaleFactor;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGBA32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGBA32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
@ -603,8 +608,8 @@ pack<RGBA32F, NoPremultiplicationOp, float, float>(const float* __restrict src,
|
||||
dst[3] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RGBA32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RGBA32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3];
|
||||
dst[0] = src[0] * scaleFactor;
|
||||
@ -613,40 +618,40 @@ pack<RGBA32F, Premultiply, float, float>(const float* __restrict src, float* __r
|
||||
dst[3] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<A32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::A32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
dst[0] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<A32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::A32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
dst[0] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<R32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::R32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<R32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::R32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3];
|
||||
dst[0] = src[0] * scaleFactor;
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RA32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
pack<RA32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
float scaleFactor = src[3];
|
||||
dst[0] = src[0] * scaleFactor;
|
||||
@ -655,13 +660,13 @@ pack<RA32F, Premultiply, float, float>(const float* __restrict src, float* __res
|
||||
|
||||
/****** END CODE SHARED WITH WEBKIT ******/
|
||||
|
||||
template<typename SrcType, typename DstType> FORCE_INLINE void
|
||||
template<typename SrcType, typename DstType> MOZ_ALWAYS_INLINE void
|
||||
convertType(const SrcType* __restrict src, DstType* __restrict dst)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(false, "Unimplemented texture format conversion");
|
||||
MOZ_ASSERT(false, "Unimplemented texture format conversion");
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
convertType<uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
@ -670,7 +675,7 @@ convertType<uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict
|
||||
dst[3] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
convertType<float, float>(const float* __restrict src, float* __restrict dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
@ -679,7 +684,7 @@ convertType<float, float>(const float* __restrict src, float* __restrict dst)
|
||||
dst[3] = src[3];
|
||||
}
|
||||
|
||||
template<> FORCE_INLINE void
|
||||
template<> MOZ_ALWAYS_INLINE void
|
||||
convertType<uint8_t, float>(const uint8_t* __restrict src, float* __restrict dst)
|
||||
{
|
||||
const float scaleFactor = 1.f / 255.0f;
|
||||
@ -689,8 +694,6 @@ convertType<uint8_t, float>(const uint8_t* __restrict src, float* __restrict dst
|
||||
dst[3] = src[3] * scaleFactor;
|
||||
}
|
||||
|
||||
#undef FORCE_INLINE
|
||||
|
||||
} // end namespace WebGLTexelConversions
|
||||
|
||||
} // end namespace mozilla
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLTexture.h"
|
||||
#include "GLContext.h"
|
||||
#include "WebGLTexelConversions.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
#include <algorithm>
|
||||
|
||||
@ -27,7 +28,7 @@ WebGLTexture::WebGLTexture(WebGLContext *context)
|
||||
, mFacesCount(0)
|
||||
, mMaxLevelWithCustomImages(0)
|
||||
, mHaveGeneratedMipmap(false)
|
||||
, mFakeBlackStatus(DoNotNeedFakeBlack)
|
||||
, mFakeBlackStatus(WebGLTextureFakeBlackStatus::IncompleteTexture)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
mContext->MakeContextCurrent();
|
||||
@ -45,7 +46,7 @@ WebGLTexture::Delete() {
|
||||
|
||||
int64_t
|
||||
WebGLTexture::ImageInfo::MemoryUsage() const {
|
||||
if (!mIsDefined)
|
||||
if (mImageDataStatus == WebGLImageDataStatus::NoImageData)
|
||||
return 0;
|
||||
int64_t texelSizeInBits = WebGLContext::GetBitsPerTexel(mFormat, mType);
|
||||
return int64_t(mWidth) * int64_t(mHeight) * texelSizeInBits / 8;
|
||||
@ -97,12 +98,6 @@ WebGLTexture::DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(GLenum texImag
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLTexture::SetDontKnowIfNeedFakeBlack() {
|
||||
mFakeBlackStatus = DontKnowIfNeedFakeBlack;
|
||||
mContext->SetDontKnowIfNeedFakeBlack();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLTexture::Bind(GLenum aTarget) {
|
||||
// this function should only be called by bindTexture().
|
||||
@ -124,7 +119,7 @@ WebGLTexture::Bind(GLenum aTarget) {
|
||||
if (firstTimeThisTextureIsBound) {
|
||||
mFacesCount = (mTarget == LOCAL_GL_TEXTURE_2D) ? 1 : 6;
|
||||
EnsureMaxLevelWithCustomImagesAtLeast(0);
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
|
||||
// thanks to the WebKit people for finding this out: GL_TEXTURE_WRAP_R is not
|
||||
// present in GLES 2, but is present in GL and it seems as if for cube maps
|
||||
@ -139,26 +134,26 @@ WebGLTexture::Bind(GLenum aTarget) {
|
||||
void
|
||||
WebGLTexture::SetImageInfo(GLenum aTarget, GLint aLevel,
|
||||
GLsizei aWidth, GLsizei aHeight,
|
||||
GLenum aFormat, GLenum aType)
|
||||
GLenum aFormat, GLenum aType, WebGLImageDataStatus aStatus)
|
||||
{
|
||||
if ( (aTarget == LOCAL_GL_TEXTURE_2D) != (mTarget == LOCAL_GL_TEXTURE_2D) )
|
||||
return;
|
||||
|
||||
EnsureMaxLevelWithCustomImagesAtLeast(aLevel);
|
||||
|
||||
ImageInfoAt(aTarget, aLevel) = ImageInfo(aWidth, aHeight, aFormat, aType);
|
||||
ImageInfoAt(aTarget, aLevel) = ImageInfo(aWidth, aHeight, aFormat, aType, aStatus);
|
||||
|
||||
if (aLevel > 0)
|
||||
SetCustomMipmap();
|
||||
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLTexture::SetGeneratedMipmap() {
|
||||
if (!mHaveGeneratedMipmap) {
|
||||
mHaveGeneratedMipmap = true;
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,128 +239,209 @@ WebGLTexture::IsMipmapCubeComplete() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLTexture::NeedFakeBlack() {
|
||||
// handle this case first, it's the generic case
|
||||
if (mFakeBlackStatus == DoNotNeedFakeBlack)
|
||||
return false;
|
||||
|
||||
if (mFakeBlackStatus == DontKnowIfNeedFakeBlack) {
|
||||
// Determine if the texture needs to be faked as a black texture.
|
||||
// See 3.8.2 Shader Execution in the OpenGL ES 2.0.24 spec.
|
||||
|
||||
for (size_t face = 0; face < mFacesCount; ++face) {
|
||||
if (!ImageInfoAtFace(face, 0).mIsDefined) {
|
||||
// In case of undefined texture image, we don't print any message because this is a very common
|
||||
// and often legitimate case, for example when doing asynchronous texture loading.
|
||||
// An extreme case of this is the photowall google demo.
|
||||
// Exiting early here allows us to avoid making noise on valid webgl code.
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const char *msg_rendering_as_black
|
||||
= "A texture is going to be rendered as if it were black, as per the OpenGL ES 2.0.24 spec section 3.8.2, "
|
||||
"because it";
|
||||
|
||||
if (mTarget == LOCAL_GL_TEXTURE_2D)
|
||||
{
|
||||
if (DoesMinFilterRequireMipmap())
|
||||
{
|
||||
if (!IsMipmapTexture2DComplete()) {
|
||||
mContext->GenerateWarning
|
||||
("%s is a 2D texture, with a minification filter requiring a mipmap, "
|
||||
"and is not mipmap complete (as defined in section 3.7.10).", msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
} else if (!ImageInfoAt(mTarget, 0).IsPowerOfTwo()) {
|
||||
mContext->GenerateWarning
|
||||
("%s is a 2D texture, with a minification filter requiring a mipmap, "
|
||||
"and either its width or height is not a power of two.", msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
}
|
||||
}
|
||||
else // no mipmap required
|
||||
{
|
||||
if (!ImageInfoAt(mTarget, 0).IsPositive()) {
|
||||
mContext->GenerateWarning
|
||||
("%s is a 2D texture and its width or height is equal to zero.",
|
||||
msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
} else if (!AreBothWrapModesClampToEdge() && !ImageInfoAt(mTarget, 0).IsPowerOfTwo()) {
|
||||
mContext->GenerateWarning
|
||||
("%s is a 2D texture, with a minification filter not requiring a mipmap, "
|
||||
"with its width or height not a power of two, and with a wrap mode "
|
||||
"different from CLAMP_TO_EDGE.", msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // cube map
|
||||
{
|
||||
bool areAllLevel0ImagesPOT = true;
|
||||
for (size_t face = 0; face < mFacesCount; ++face)
|
||||
areAllLevel0ImagesPOT &= ImageInfoAtFace(face, 0).IsPowerOfTwo();
|
||||
|
||||
if (DoesMinFilterRequireMipmap())
|
||||
{
|
||||
if (!IsMipmapCubeComplete()) {
|
||||
mContext->GenerateWarning("%s is a cube map texture, with a minification filter requiring a mipmap, "
|
||||
"and is not mipmap cube complete (as defined in section 3.7.10).",
|
||||
msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
} else if (!areAllLevel0ImagesPOT) {
|
||||
mContext->GenerateWarning("%s is a cube map texture, with a minification filter requiring a mipmap, "
|
||||
"and either the width or the height of some level 0 image is not a power of two.",
|
||||
msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
}
|
||||
}
|
||||
else // no mipmap required
|
||||
{
|
||||
if (!IsCubeComplete()) {
|
||||
mContext->GenerateWarning("%s is a cube map texture, with a minification filter not requiring a mipmap, "
|
||||
"and is not cube complete (as defined in section 3.7.10).",
|
||||
msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
} else if (!AreBothWrapModesClampToEdge() && !areAllLevel0ImagesPOT) {
|
||||
mContext->GenerateWarning("%s is a cube map texture, with a minification filter not requiring a mipmap, "
|
||||
"with some level 0 image having width or height not a power of two, and with a wrap mode "
|
||||
"different from CLAMP_TO_EDGE.", msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ImageInfoBase().mType == LOCAL_GL_FLOAT &&
|
||||
!Context()->IsExtensionEnabled(WebGLContext::OES_texture_float_linear))
|
||||
{
|
||||
if (mMinFilter == LOCAL_GL_LINEAR ||
|
||||
mMinFilter == LOCAL_GL_LINEAR_MIPMAP_LINEAR ||
|
||||
mMinFilter == LOCAL_GL_LINEAR_MIPMAP_NEAREST ||
|
||||
mMinFilter == LOCAL_GL_NEAREST_MIPMAP_LINEAR)
|
||||
{
|
||||
mContext->GenerateWarning("%s is a texture with a linear minification filter, "
|
||||
"which is not compatible with gl.FLOAT by default. "
|
||||
"Try enabling the OES_texture_float_linear extension if supported.", msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
}
|
||||
else if (mMagFilter == LOCAL_GL_LINEAR)
|
||||
{
|
||||
mContext->GenerateWarning("%s is a texture with a linear magnification filter, "
|
||||
"which is not compatible with gl.FLOAT by default. "
|
||||
"Try enabling the OES_texture_float_linear extension if supported.", msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
}
|
||||
}
|
||||
|
||||
// we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
|
||||
// that means that we do NOT need it.
|
||||
if (mFakeBlackStatus == DontKnowIfNeedFakeBlack)
|
||||
mFakeBlackStatus = DoNotNeedFakeBlack;
|
||||
WebGLTextureFakeBlackStatus
|
||||
WebGLTexture::ResolvedFakeBlackStatus() {
|
||||
if (MOZ_LIKELY(mFakeBlackStatus != WebGLTextureFakeBlackStatus::Unknown)) {
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
|
||||
return mFakeBlackStatus == DoNeedFakeBlack;
|
||||
// Determine if the texture needs to be faked as a black texture.
|
||||
// See 3.8.2 Shader Execution in the OpenGL ES 2.0.24 spec.
|
||||
|
||||
for (size_t face = 0; face < mFacesCount; ++face) {
|
||||
if (ImageInfoAtFace(face, 0).mImageDataStatus == WebGLImageDataStatus::NoImageData) {
|
||||
// In case of undefined texture image, we don't print any message because this is a very common
|
||||
// and often legitimate case (asynchronous texture loading).
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
}
|
||||
|
||||
const char *msg_rendering_as_black
|
||||
= "A texture is going to be rendered as if it were black, as per the OpenGL ES 2.0.24 spec section 3.8.2, "
|
||||
"because it";
|
||||
|
||||
if (mTarget == LOCAL_GL_TEXTURE_2D)
|
||||
{
|
||||
if (DoesMinFilterRequireMipmap())
|
||||
{
|
||||
if (!IsMipmapTexture2DComplete()) {
|
||||
mContext->GenerateWarning
|
||||
("%s is a 2D texture, with a minification filter requiring a mipmap, "
|
||||
"and is not mipmap complete (as defined in section 3.7.10).", msg_rendering_as_black);
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
} else if (!ImageInfoAt(mTarget, 0).IsPowerOfTwo()) {
|
||||
mContext->GenerateWarning
|
||||
("%s is a 2D texture, with a minification filter requiring a mipmap, "
|
||||
"and either its width or height is not a power of two.", msg_rendering_as_black);
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
}
|
||||
}
|
||||
else // no mipmap required
|
||||
{
|
||||
if (!ImageInfoAt(mTarget, 0).IsPositive()) {
|
||||
mContext->GenerateWarning
|
||||
("%s is a 2D texture and its width or height is equal to zero.",
|
||||
msg_rendering_as_black);
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
} else if (!AreBothWrapModesClampToEdge() && !ImageInfoAt(mTarget, 0).IsPowerOfTwo()) {
|
||||
mContext->GenerateWarning
|
||||
("%s is a 2D texture, with a minification filter not requiring a mipmap, "
|
||||
"with its width or height not a power of two, and with a wrap mode "
|
||||
"different from CLAMP_TO_EDGE.", msg_rendering_as_black);
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // cube map
|
||||
{
|
||||
bool areAllLevel0ImagesPOT = true;
|
||||
for (size_t face = 0; face < mFacesCount; ++face)
|
||||
areAllLevel0ImagesPOT &= ImageInfoAtFace(face, 0).IsPowerOfTwo();
|
||||
|
||||
if (DoesMinFilterRequireMipmap())
|
||||
{
|
||||
if (!IsMipmapCubeComplete()) {
|
||||
mContext->GenerateWarning("%s is a cube map texture, with a minification filter requiring a mipmap, "
|
||||
"and is not mipmap cube complete (as defined in section 3.7.10).",
|
||||
msg_rendering_as_black);
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
} else if (!areAllLevel0ImagesPOT) {
|
||||
mContext->GenerateWarning("%s is a cube map texture, with a minification filter requiring a mipmap, "
|
||||
"and either the width or the height of some level 0 image is not a power of two.",
|
||||
msg_rendering_as_black);
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
}
|
||||
}
|
||||
else // no mipmap required
|
||||
{
|
||||
if (!IsCubeComplete()) {
|
||||
mContext->GenerateWarning("%s is a cube map texture, with a minification filter not requiring a mipmap, "
|
||||
"and is not cube complete (as defined in section 3.7.10).",
|
||||
msg_rendering_as_black);
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
} else if (!AreBothWrapModesClampToEdge() && !areAllLevel0ImagesPOT) {
|
||||
mContext->GenerateWarning("%s is a cube map texture, with a minification filter not requiring a mipmap, "
|
||||
"with some level 0 image having width or height not a power of two, and with a wrap mode "
|
||||
"different from CLAMP_TO_EDGE.", msg_rendering_as_black);
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ImageInfoBase().mType == LOCAL_GL_FLOAT &&
|
||||
!Context()->IsExtensionEnabled(WebGLContext::OES_texture_float_linear))
|
||||
{
|
||||
if (mMinFilter == LOCAL_GL_LINEAR ||
|
||||
mMinFilter == LOCAL_GL_LINEAR_MIPMAP_LINEAR ||
|
||||
mMinFilter == LOCAL_GL_LINEAR_MIPMAP_NEAREST ||
|
||||
mMinFilter == LOCAL_GL_NEAREST_MIPMAP_LINEAR)
|
||||
{
|
||||
mContext->GenerateWarning("%s is a texture with a linear minification filter, "
|
||||
"which is not compatible with gl.FLOAT by default. "
|
||||
"Try enabling the OES_texture_float_linear extension if supported.", msg_rendering_as_black);
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
}
|
||||
else if (mMagFilter == LOCAL_GL_LINEAR)
|
||||
{
|
||||
mContext->GenerateWarning("%s is a texture with a linear magnification filter, "
|
||||
"which is not compatible with gl.FLOAT by default. "
|
||||
"Try enabling the OES_texture_float_linear extension if supported.", msg_rendering_as_black);
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
}
|
||||
}
|
||||
|
||||
// We have exhausted all cases of incomplete textures, where we would need opaque black.
|
||||
// We may still need transparent black in case of uninitialized image data.
|
||||
bool hasUninitializedImageData = false;
|
||||
for (size_t level = 0; level <= mMaxLevelWithCustomImages; ++level) {
|
||||
for (size_t face = 0; face < mFacesCount; ++face) {
|
||||
hasUninitializedImageData |= (ImageInfoAtFace(face, level).mImageDataStatus == WebGLImageDataStatus::UninitializedImageData);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasUninitializedImageData) {
|
||||
bool hasAnyInitializedImageData = false;
|
||||
for (size_t level = 0; level <= mMaxLevelWithCustomImages; ++level) {
|
||||
for (size_t face = 0; face < mFacesCount; ++face) {
|
||||
if (ImageInfoAtFace(face, level).mImageDataStatus == WebGLImageDataStatus::InitializedImageData) {
|
||||
hasAnyInitializedImageData = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasAnyInitializedImageData) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasAnyInitializedImageData) {
|
||||
// The texture contains some initialized image data, and some uninitialized image data.
|
||||
// In this case, we have no choice but to initialize all image data now. Fortunately,
|
||||
// in this case we know that we can't be dealing with a depth texture per WEBGL_depth_texture
|
||||
// and ANGLE_depth_texture (which allow only one image per texture) so we can assume that
|
||||
// glTexImage2D is able to upload data to images.
|
||||
for (size_t level = 0; level <= mMaxLevelWithCustomImages; ++level) {
|
||||
for (size_t face = 0; face < mFacesCount; ++face) {
|
||||
GLenum imageTarget = mTarget == LOCAL_GL_TEXTURE_2D
|
||||
? LOCAL_GL_TEXTURE_2D
|
||||
: LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
|
||||
const ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
|
||||
if (imageInfo.mImageDataStatus == WebGLImageDataStatus::UninitializedImageData) {
|
||||
DoDeferredImageInitialization(imageTarget, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded;
|
||||
} else {
|
||||
// The texture only contains uninitialized image data. In this case,
|
||||
// we can use a black texture for it.
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::UninitializedImageData;
|
||||
}
|
||||
}
|
||||
|
||||
// we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
|
||||
// that means that we do NOT need it.
|
||||
if (mFakeBlackStatus == WebGLTextureFakeBlackStatus::Unknown) {
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mFakeBlackStatus != WebGLTextureFakeBlackStatus::Unknown);
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLTexture::DoDeferredImageInitialization(GLenum imageTarget, GLint level)
|
||||
{
|
||||
const ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
|
||||
MOZ_ASSERT(imageInfo.mImageDataStatus == WebGLImageDataStatus::UninitializedImageData);
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
gl::ScopedBindTexture autoBindTex(mContext->gl, GLName(), mTarget);
|
||||
|
||||
WebGLTexelFormat texelformat = GetWebGLTexelFormat(imageInfo.mFormat, imageInfo.mType);
|
||||
uint32_t texelsize = WebGLTexelConversions::TexelBytesForFormat(texelformat);
|
||||
CheckedUint32 checked_byteLength
|
||||
= WebGLContext::GetImageSize(
|
||||
imageInfo.mHeight,
|
||||
imageInfo.mWidth,
|
||||
texelsize,
|
||||
mContext->mPixelStoreUnpackAlignment);
|
||||
MOZ_ASSERT(checked_byteLength.isValid()); // should have been checked earlier
|
||||
void *zeros = calloc(1, checked_byteLength.value());
|
||||
GLenum error
|
||||
= mContext->CheckedTexImage2D(imageTarget, level, imageInfo.mFormat,
|
||||
imageInfo.mWidth, imageInfo.mHeight,
|
||||
0, imageInfo.mFormat, imageInfo.mType,
|
||||
zeros);
|
||||
|
||||
free(zeros);
|
||||
SetImageDataStatus(imageTarget, level, WebGLImageDataStatus::InitializedImageData);
|
||||
|
||||
if (error) {
|
||||
// Should only be OUT_OF_MEMORY. Anyway, there's no good way to recover from this here.
|
||||
MOZ_CRASH(); // errors on texture upload have been related to video memory exposure in the past.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTexture)
|
||||
|
@ -21,6 +21,15 @@ inline bool is_pot_assuming_nonnegative(GLsizei x)
|
||||
return x && (x & (x-1)) == 0;
|
||||
}
|
||||
|
||||
inline bool FormatHasAlpha(GLenum format)
|
||||
{
|
||||
return format == LOCAL_GL_RGBA ||
|
||||
format == LOCAL_GL_LUMINANCE_ALPHA ||
|
||||
format == LOCAL_GL_ALPHA ||
|
||||
format == LOCAL_GL_RGBA4 ||
|
||||
format == LOCAL_GL_RGB5_A1;
|
||||
}
|
||||
|
||||
// NOTE: When this class is switched to new DOM bindings, update the (then-slow)
|
||||
// WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
|
||||
class WebGLTexture MOZ_FINAL
|
||||
@ -66,28 +75,33 @@ protected:
|
||||
|
||||
public:
|
||||
|
||||
class ImageInfo : public WebGLRectangleObject {
|
||||
class ImageInfo
|
||||
: public WebGLRectangleObject
|
||||
{
|
||||
public:
|
||||
ImageInfo()
|
||||
: mFormat(0)
|
||||
, mType(0)
|
||||
, mIsDefined(false)
|
||||
, mImageDataStatus(WebGLImageDataStatus::NoImageData)
|
||||
{}
|
||||
|
||||
ImageInfo(GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type)
|
||||
GLenum format, GLenum type, WebGLImageDataStatus status)
|
||||
: WebGLRectangleObject(width, height)
|
||||
, mFormat(format)
|
||||
, mType(type)
|
||||
, mIsDefined(true)
|
||||
{}
|
||||
, mImageDataStatus(status)
|
||||
{
|
||||
// shouldn't use this constructor to construct a null ImageInfo
|
||||
MOZ_ASSERT(status != WebGLImageDataStatus::NoImageData);
|
||||
}
|
||||
|
||||
bool operator==(const ImageInfo& a) const {
|
||||
return mIsDefined == a.mIsDefined &&
|
||||
mWidth == a.mWidth &&
|
||||
mHeight == a.mHeight &&
|
||||
mFormat == a.mFormat &&
|
||||
mType == a.mType;
|
||||
return mImageDataStatus == a.mImageDataStatus &&
|
||||
mWidth == a.mWidth &&
|
||||
mHeight == a.mHeight &&
|
||||
mFormat == a.mFormat &&
|
||||
mType == a.mType;
|
||||
}
|
||||
bool operator!=(const ImageInfo& a) const {
|
||||
return !(*this == a);
|
||||
@ -102,12 +116,15 @@ public:
|
||||
return is_pot_assuming_nonnegative(mWidth) &&
|
||||
is_pot_assuming_nonnegative(mHeight); // negative sizes should never happen (caught in texImage2D...)
|
||||
}
|
||||
bool HasUninitializedImageData() const {
|
||||
return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
|
||||
}
|
||||
int64_t MemoryUsage() const;
|
||||
GLenum Format() const { return mFormat; }
|
||||
GLenum Type() const { return mType; }
|
||||
protected:
|
||||
GLenum mFormat, mType;
|
||||
bool mIsDefined;
|
||||
WebGLImageDataStatus mImageDataStatus;
|
||||
|
||||
friend class WebGLTexture;
|
||||
};
|
||||
@ -149,12 +166,12 @@ public:
|
||||
|
||||
bool HasImageInfoAt(GLenum imageTarget, GLint level) const {
|
||||
MOZ_ASSERT(imageTarget);
|
||||
|
||||
|
||||
size_t face = FaceForTarget(imageTarget);
|
||||
CheckedUint32 checked_index = CheckedUint32(level) * mFacesCount + face;
|
||||
return checked_index.isValid() &&
|
||||
checked_index.value() < mImageInfos.Length() &&
|
||||
ImageInfoAt(imageTarget, level).mIsDefined;
|
||||
ImageInfoAt(imageTarget, level).mImageDataStatus != WebGLImageDataStatus::NoImageData;
|
||||
}
|
||||
|
||||
ImageInfo& ImageInfoBase() {
|
||||
@ -167,6 +184,20 @@ public:
|
||||
|
||||
int64_t MemoryUsage() const;
|
||||
|
||||
void SetImageDataStatus(GLenum imageTarget, GLint level, WebGLImageDataStatus newStatus) {
|
||||
MOZ_ASSERT(HasImageInfoAt(imageTarget, level));
|
||||
ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
|
||||
// there is no way to go from having image data to not having any
|
||||
MOZ_ASSERT(newStatus != WebGLImageDataStatus::NoImageData ||
|
||||
imageInfo.mImageDataStatus == WebGLImageDataStatus::NoImageData);
|
||||
if (imageInfo.mImageDataStatus != newStatus) {
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
imageInfo.mImageDataStatus = newStatus;
|
||||
}
|
||||
|
||||
void DoDeferredImageInitialization(GLenum imageTarget, GLint level);
|
||||
|
||||
protected:
|
||||
|
||||
GLenum mTarget;
|
||||
@ -176,7 +207,7 @@ protected:
|
||||
nsTArray<ImageInfo> mImageInfos;
|
||||
|
||||
bool mHaveGeneratedMipmap;
|
||||
FakeBlackStatus mFakeBlackStatus;
|
||||
WebGLTextureFakeBlackStatus mFakeBlackStatus;
|
||||
|
||||
void EnsureMaxLevelWithCustomImagesAtLeast(size_t aMaxLevelWithCustomImages) {
|
||||
mMaxLevelWithCustomImages = std::max(mMaxLevelWithCustomImages, aMaxLevelWithCustomImages);
|
||||
@ -197,29 +228,27 @@ protected:
|
||||
|
||||
public:
|
||||
|
||||
void SetDontKnowIfNeedFakeBlack();
|
||||
|
||||
void Bind(GLenum aTarget);
|
||||
|
||||
void SetImageInfo(GLenum aTarget, GLint aLevel,
|
||||
GLsizei aWidth, GLsizei aHeight,
|
||||
GLenum aFormat, GLenum aType);
|
||||
GLenum aFormat, GLenum aType, WebGLImageDataStatus aStatus);
|
||||
|
||||
void SetMinFilter(GLenum aMinFilter) {
|
||||
mMinFilter = aMinFilter;
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
void SetMagFilter(GLenum aMagFilter) {
|
||||
mMagFilter = aMagFilter;
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
void SetWrapS(GLenum aWrapS) {
|
||||
mWrapS = aWrapS;
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
void SetWrapT(GLenum aWrapT) {
|
||||
mWrapT = aWrapT;
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
GLenum MinFilter() const { return mMinFilter; }
|
||||
|
||||
@ -243,7 +272,13 @@ public:
|
||||
|
||||
bool IsMipmapCubeComplete() const;
|
||||
|
||||
bool NeedFakeBlack();
|
||||
void SetFakeBlackStatus(WebGLTextureFakeBlackStatus x) {
|
||||
mFakeBlackStatus = x;
|
||||
mContext->SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown);
|
||||
}
|
||||
// Returns the current fake-black-status, except if it was Unknown,
|
||||
// in which case this function resolves it first, so it never returns Unknown.
|
||||
WebGLTextureFakeBlackStatus ResolvedFakeBlackStatus();
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -6,6 +6,8 @@
|
||||
#ifndef WEBGLTYPES_H_
|
||||
#define WEBGLTYPES_H_
|
||||
|
||||
#include "mozilla/TypedEnum.h"
|
||||
|
||||
// Most WebIDL typedefs are identical to their OpenGL counterparts.
|
||||
#include "GLTypes.h"
|
||||
|
||||
@ -17,13 +19,73 @@ typedef bool WebGLboolean;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum FakeBlackStatus { DoNotNeedFakeBlack, DoNeedFakeBlack, DontKnowIfNeedFakeBlack };
|
||||
/*
|
||||
* WebGLContextFakeBlackStatus and WebGLTextureFakeBlackStatus are enums to
|
||||
* track what needs to use a dummy 1x1 black texture, which we refer to as a
|
||||
* 'fake black' texture.
|
||||
*
|
||||
* There are generally two things that can cause us to use such 'fake black'
|
||||
* textures:
|
||||
*
|
||||
* (1) OpenGL ES rules on sampling incomplete textures specify that they
|
||||
* must be sampled as RGBA(0, 0, 0, 1) (opaque black). We have to implement these rules
|
||||
* ourselves, if only because we do not always run on OpenGL ES, and also
|
||||
* because this is dangerously close to the kind of case where we don't
|
||||
* want to trust the driver with corner cases of texture memory accesses.
|
||||
*
|
||||
* (2) OpenGL has cases where a renderbuffer, or a texture image, can contain
|
||||
* uninitialized image data. See below the comment about WebGLImageDataStatus.
|
||||
* WebGL must never have access to uninitialized image data. The WebGL 1 spec,
|
||||
* section 4.1 'Resource Restrictions', specifies that in any such case, the
|
||||
* uninitialized image data must be exposed to WebGL as if it were filled
|
||||
* with zero bytes, which means it's either opaque or transparent black
|
||||
* depending on whether the image format has alpha.
|
||||
*
|
||||
* Why are there _two_ separate enums there, WebGLContextFakeBlackStatus
|
||||
* and WebGLTextureFakeBlackStatus? That's because each texture must know the precise
|
||||
* reason why it needs to be faked (incomplete texture vs. uninitialized image data),
|
||||
* whereas the WebGL context can only know whether _any_ faking is currently needed at all.
|
||||
*/
|
||||
MOZ_BEGIN_ENUM_CLASS(WebGLContextFakeBlackStatus, int)
|
||||
Unknown,
|
||||
NotNeeded,
|
||||
Needed
|
||||
MOZ_END_ENUM_CLASS(WebGLContextFakeBlackStatus)
|
||||
|
||||
struct VertexAttrib0Status {
|
||||
enum { Default, EmulatedUninitializedArray, EmulatedInitializedArray };
|
||||
};
|
||||
MOZ_BEGIN_ENUM_CLASS(WebGLTextureFakeBlackStatus, int)
|
||||
Unknown,
|
||||
NotNeeded,
|
||||
IncompleteTexture,
|
||||
UninitializedImageData
|
||||
MOZ_END_ENUM_CLASS(WebGLTextureFakeBlackStatus)
|
||||
|
||||
namespace WebGLTexelConversions {
|
||||
/*
|
||||
* Implementing WebGL (or OpenGL ES 2.0) on top of desktop OpenGL requires
|
||||
* emulating the vertex attrib 0 array when it's not enabled. Indeed,
|
||||
* OpenGL ES 2.0 allows drawing without vertex attrib 0 array enabled, but
|
||||
* desktop OpenGL does not allow that.
|
||||
*/
|
||||
MOZ_BEGIN_ENUM_CLASS(WebGLVertexAttrib0Status, int)
|
||||
Default, // default status - no emulation needed
|
||||
EmulatedUninitializedArray, // need an artificial attrib 0 array, but contents may be left uninitialized
|
||||
EmulatedInitializedArray // need an artificial attrib 0 array, and contents must be initialized
|
||||
MOZ_END_ENUM_CLASS(WebGLVertexAttrib0Status)
|
||||
|
||||
/*
|
||||
* Enum to track the status of image data (renderbuffer or texture image) presence
|
||||
* and initialization.
|
||||
*
|
||||
* - NoImageData is the initial state before any image data is allocated.
|
||||
* - InitializedImageData is the state after image data is allocated and initialized.
|
||||
* - UninitializedImageData is an intermediate state where data is allocated but not
|
||||
* initialized. It is the state that renderbuffers are in after a renderbufferStorage call,
|
||||
* and it is the state that texture images are in after a texImage2D call with null data.
|
||||
*/
|
||||
MOZ_BEGIN_ENUM_CLASS(WebGLImageDataStatus, int)
|
||||
NoImageData,
|
||||
UninitializedImageData,
|
||||
InitializedImageData
|
||||
MOZ_END_ENUM_CLASS(WebGLImageDataStatus)
|
||||
|
||||
/*
|
||||
* The formats that may participate, either as source or destination formats,
|
||||
@ -33,8 +95,7 @@ namespace WebGLTexelConversions {
|
||||
* - additional source formats, depending on browser details, used when uploading
|
||||
* textures from DOM elements. See gfxImageSurface::Format().
|
||||
*/
|
||||
enum WebGLTexelFormat
|
||||
{
|
||||
MOZ_BEGIN_ENUM_CLASS(WebGLTexelFormat, int)
|
||||
// dummy error code returned by GetWebGLTexelFormat in error cases,
|
||||
// after assertion failure (so this never happens in debug builds)
|
||||
BadFormat,
|
||||
@ -64,9 +125,7 @@ enum WebGLTexelFormat
|
||||
RGBA5551,
|
||||
RGBA4444,
|
||||
RGBA32F // used for OES_texture_float extension
|
||||
};
|
||||
|
||||
} // end namespace WebGLTexelConversions
|
||||
MOZ_END_ENUM_CLASS(WebGLTexelFormat)
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -44,7 +44,7 @@ struct WebGLUniformInfo {
|
||||
case SH_FLOAT_MAT4:
|
||||
return 16;
|
||||
default:
|
||||
NS_ABORT(); // should never get here
|
||||
MOZ_ASSERT(false); // should never get here
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -34,10 +34,10 @@ void WebGLVertexArray::Delete() {
|
||||
}
|
||||
|
||||
mBoundElementArrayBuffer = nullptr;
|
||||
mAttribBuffers.Clear();
|
||||
mAttribs.Clear();
|
||||
}
|
||||
|
||||
bool WebGLVertexArray::EnsureAttribIndex(GLuint index, const char *info)
|
||||
bool WebGLVertexArray::EnsureAttrib(GLuint index, const char *info)
|
||||
{
|
||||
if (index >= GLuint(mContext->mGLMaxVertexAttribs)) {
|
||||
if (index == GLuint(-1)) {
|
||||
@ -49,15 +49,15 @@ bool WebGLVertexArray::EnsureAttribIndex(GLuint index, const char *info)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (index >= mAttribBuffers.Length()) {
|
||||
mAttribBuffers.SetLength(index + 1);
|
||||
else if (index >= mAttribs.Length()) {
|
||||
mAttribs.SetLength(index + 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(WebGLVertexArray,
|
||||
mAttribBuffers,
|
||||
mAttribs,
|
||||
mBoundElementArrayBuffer)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLVertexArray, AddRef)
|
||||
|
@ -59,7 +59,13 @@ public:
|
||||
void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
|
||||
GLuint GLName() const { return mGLName; }
|
||||
|
||||
bool EnsureAttribIndex(GLuint index, const char *info);
|
||||
bool EnsureAttrib(GLuint index, const char *info);
|
||||
bool HasAttrib(GLuint index) {
|
||||
return index < mAttribs.Length();
|
||||
}
|
||||
bool IsAttribArrayEnabled(GLuint index) {
|
||||
return HasAttrib(index) && mAttribs[index].enabled;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -71,7 +77,7 @@ private:
|
||||
|
||||
GLuint mGLName;
|
||||
bool mHasEverBeenBound;
|
||||
nsTArray<WebGLVertexAttribData> mAttribBuffers;
|
||||
nsTArray<WebGLVertexAttribData> mAttribs;
|
||||
WebGLRefPtr<WebGLBuffer> mBoundElementArrayBuffer;
|
||||
|
||||
|
||||
|
@ -608,5 +608,17 @@ AudioContext::Unmute() const
|
||||
mDestination->Unmute();
|
||||
}
|
||||
|
||||
AudioChannel
|
||||
AudioContext::MozAudioChannelType() const
|
||||
{
|
||||
return mDestination->MozAudioChannelType();
|
||||
}
|
||||
|
||||
void
|
||||
AudioContext::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv)
|
||||
{
|
||||
mDestination->SetMozAudioChannelType(aValue, aRv);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef AudioContext_h_
|
||||
#define AudioContext_h_
|
||||
|
||||
#include "mozilla/dom/AudioContextBinding.h"
|
||||
#include "EnableWebAudioCheck.h"
|
||||
#include "MediaBufferDecoder.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
@ -238,6 +239,9 @@ public:
|
||||
|
||||
JSContext* GetJSContext() const;
|
||||
|
||||
AudioChannel MozAudioChannelType() const;
|
||||
void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
void RemoveFromDecodeQueue(WebAudioDecodeJob* aDecodeJob);
|
||||
void ShutdownDecoder();
|
||||
|
@ -14,7 +14,9 @@
|
||||
#include "OfflineAudioCompletionEvent.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -244,6 +246,7 @@ AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
|
||||
ChannelCountMode::Explicit,
|
||||
ChannelInterpretation::Speakers)
|
||||
, mFramesToProduce(aLength)
|
||||
, mAudioChannel(AudioChannel::Normal)
|
||||
{
|
||||
MediaStreamGraph* graph = aIsOffline ?
|
||||
MediaStreamGraph::CreateNonRealtimeInstance() :
|
||||
@ -256,10 +259,6 @@ AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
|
||||
mStream = graph->CreateAudioNodeStream(engine, MediaStreamGraph::EXTERNAL_STREAM);
|
||||
|
||||
if (!aIsOffline && UseAudioChannelService()) {
|
||||
mAudioChannelAgent = new AudioChannelAgent();
|
||||
mAudioChannelAgent->InitWithWeakCallback(nsIAudioChannelAgent::AUDIO_AGENT_CHANNEL_NORMAL,
|
||||
this);
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
|
||||
if (target) {
|
||||
target->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"), this,
|
||||
@ -267,16 +266,7 @@ AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
|
||||
/* wantsUntrusted = */ false);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
|
||||
if (docshell) {
|
||||
bool isActive = false;
|
||||
docshell->GetIsActive(&isActive);
|
||||
mAudioChannelAgent->SetVisibilityState(isActive);
|
||||
}
|
||||
|
||||
int32_t state = 0;
|
||||
mAudioChannelAgent->StartPlaying(&state);
|
||||
SetCanPlay(state == AudioChannelState::AUDIO_CHANNEL_STATE_NORMAL);
|
||||
CreateAudioChannelAgent();
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,5 +381,117 @@ AudioDestinationNode::CanPlayChanged(int32_t aCanPlay)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
AudioChannel
|
||||
AudioDestinationNode::MozAudioChannelType() const
|
||||
{
|
||||
return mAudioChannel;
|
||||
}
|
||||
|
||||
void
|
||||
AudioDestinationNode::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv)
|
||||
{
|
||||
if (Context()->IsOffline()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aValue != mAudioChannel &&
|
||||
CheckAudioChannelPermissions(aValue)) {
|
||||
mAudioChannel = aValue;
|
||||
|
||||
if (mAudioChannelAgent) {
|
||||
CreateAudioChannelAgent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AudioDestinationNode::CheckAudioChannelPermissions(AudioChannel aValue)
|
||||
{
|
||||
if (!Preferences::GetBool("media.useAudioChannelService")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only normal channel doesn't need permission.
|
||||
if (aValue == AudioChannel::Normal) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permissionManager =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
if (!permissionManager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(GetOwner());
|
||||
NS_ASSERTION(sop, "Window didn't QI to nsIScriptObjectPrincipal!");
|
||||
nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal();
|
||||
|
||||
uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
|
||||
|
||||
nsCString channel;
|
||||
channel.AssignASCII(AudioChannelValues::strings[uint32_t(aValue)].value,
|
||||
AudioChannelValues::strings[uint32_t(aValue)].length);
|
||||
permissionManager->TestExactPermissionFromPrincipal(principal,
|
||||
nsCString(NS_LITERAL_CSTRING("audio-channel-") + channel).get(),
|
||||
&perm);
|
||||
|
||||
return perm == nsIPermissionManager::ALLOW_ACTION;
|
||||
}
|
||||
|
||||
void
|
||||
AudioDestinationNode::CreateAudioChannelAgent()
|
||||
{
|
||||
if (mAudioChannelAgent) {
|
||||
mAudioChannelAgent->StopPlaying();
|
||||
}
|
||||
|
||||
AudioChannelType type = AUDIO_CHANNEL_NORMAL;
|
||||
switch(mAudioChannel) {
|
||||
case AudioChannel::Normal:
|
||||
type = AUDIO_CHANNEL_NORMAL;
|
||||
break;
|
||||
|
||||
case AudioChannel::Content:
|
||||
type = AUDIO_CHANNEL_CONTENT;
|
||||
break;
|
||||
|
||||
case AudioChannel::Notification:
|
||||
type = AUDIO_CHANNEL_NOTIFICATION;
|
||||
break;
|
||||
|
||||
case AudioChannel::Alarm:
|
||||
type = AUDIO_CHANNEL_ALARM;
|
||||
break;
|
||||
|
||||
case AudioChannel::Telephony:
|
||||
type = AUDIO_CHANNEL_TELEPHONY;
|
||||
break;
|
||||
|
||||
case AudioChannel::Ringer:
|
||||
type = AUDIO_CHANNEL_RINGER;
|
||||
break;
|
||||
|
||||
case AudioChannel::Publicnotification:
|
||||
type = AUDIO_CHANNEL_PUBLICNOTIFICATION;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
mAudioChannelAgent = new AudioChannelAgent();
|
||||
mAudioChannelAgent->InitWithWeakCallback(type, this);
|
||||
|
||||
nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
|
||||
if (docshell) {
|
||||
bool isActive = false;
|
||||
docshell->GetIsActive(&isActive);
|
||||
mAudioChannelAgent->SetVisibilityState(isActive);
|
||||
}
|
||||
|
||||
int32_t state = 0;
|
||||
mAudioChannelAgent->StartPlaying(&state);
|
||||
SetCanPlay(state == AudioChannelState::AUDIO_CHANNEL_STATE_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,9 +7,11 @@
|
||||
#ifndef AudioDestinationNode_h_
|
||||
#define AudioDestinationNode_h_
|
||||
|
||||
#include "mozilla/dom/AudioContextBinding.h"
|
||||
#include "AudioNode.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIAudioChannelAgent.h"
|
||||
#include "AudioChannelCommon.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -59,13 +61,22 @@ public:
|
||||
// nsIAudioChannelAgentCallback
|
||||
NS_IMETHOD CanPlayChanged(int32_t aCanPlay);
|
||||
|
||||
AudioChannel MozAudioChannelType() const;
|
||||
void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
bool CheckAudioChannelPermissions(AudioChannel aValue);
|
||||
void CreateAudioChannelAgent();
|
||||
|
||||
void SetCanPlay(bool aCanPlay);
|
||||
|
||||
SelfReference<AudioDestinationNode> mOfflineRenderingRef;
|
||||
uint32_t mFramesToProduce;
|
||||
|
||||
nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
|
||||
|
||||
// Audio Channel Type.
|
||||
AudioChannel mAudioChannel;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -110,3 +110,4 @@ support-files =
|
||||
[test_waveShaperNoCurve.html]
|
||||
[test_waveShaperZeroLengthCurve.html]
|
||||
[test_audioDestinationNode.html]
|
||||
[test_mozaudiochannel.html]
|
||||
|
90
content/media/webaudio/test/test_mozaudiochannel.html
Normal file
90
content/media/webaudio/test/test_mozaudiochannel.html
Normal file
@ -0,0 +1,90 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for mozaudiochannel</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
function test_basic() {
|
||||
var ac = new AudioContext();
|
||||
ok(ac, "AudioContext created");
|
||||
|
||||
// Default
|
||||
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
|
||||
|
||||
// random wrong channel
|
||||
ac.mozAudioChannelType = "foo";
|
||||
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
|
||||
|
||||
// Unpermitted channels
|
||||
ac.mozAudioChannelType = "content";
|
||||
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
|
||||
|
||||
ac.mozAudioChannelType = "notification";
|
||||
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
|
||||
|
||||
ac.mozAudioChannelType = "alarm";
|
||||
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
|
||||
|
||||
ac.mozAudioChannelType = "telephony";
|
||||
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
|
||||
|
||||
ac.mozAudioChannelType = "ringer";
|
||||
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
|
||||
|
||||
ac.mozAudioChannelType = "publicnotification";
|
||||
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
|
||||
|
||||
runTest();
|
||||
}
|
||||
|
||||
function test_permission(aChannel) {
|
||||
var ac = new AudioContext();
|
||||
ok(ac, "AudioContext created");
|
||||
|
||||
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
|
||||
|
||||
SpecialPowers.pushPermissions(
|
||||
[{ "type": "audio-channel-" + aChannel, "allow": 1, "context": document }],
|
||||
function() {
|
||||
ac.mozAudioChannelType = aChannel;
|
||||
is(ac.mozAudioChannelType, aChannel, "Default ac channel == '" + aChannel + "'");
|
||||
runTest();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
test_basic,
|
||||
|
||||
function() { test_permission("content"); },
|
||||
function() { test_permission("notification"); },
|
||||
function() { test_permission("alarm"); },
|
||||
function() { test_permission("telephony"); },
|
||||
function() { test_permission("ringer"); },
|
||||
function() { test_permission("publicnotification"); }
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true ]]}, runTest);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -98,4 +98,19 @@ partial interface AudioContext {
|
||||
optional unsigned long numberOfOutputChannels = 2);
|
||||
};
|
||||
|
||||
enum AudioChannel {
|
||||
"normal",
|
||||
"content",
|
||||
"notification",
|
||||
"alarm",
|
||||
"telephony",
|
||||
"ringer",
|
||||
"publicnotification",
|
||||
};
|
||||
|
||||
// Mozilla extensions
|
||||
partial interface AudioContext {
|
||||
// Read HTMLMediaElement.webidl for more information about this attribute.
|
||||
[Pref="media.useAudioChannelService", SetterThrows]
|
||||
attribute AudioChannel mozAudioChannelType;
|
||||
};
|
||||
|
@ -381,6 +381,83 @@ DrawTargetCG::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops,
|
||||
return new GradientStopsCG(aStops, aNumStops, aExtendMode);
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateLinearParametersToIncludePoint(double *min_t, double *max_t,
|
||||
CGPoint *start,
|
||||
double dx, double dy,
|
||||
double x, double y)
|
||||
{
|
||||
/**
|
||||
* Compute a parameter t such that a line perpendicular to the (dx,dy)
|
||||
* vector, passing through (start->x + dx*t, start->y + dy*t), also
|
||||
* passes through (x,y).
|
||||
*
|
||||
* Let px = x - start->x, py = y - start->y.
|
||||
* t is given by
|
||||
* (px - dx*t)*dx + (py - dy*t)*dy = 0
|
||||
*
|
||||
* Solving for t we get
|
||||
* numerator = dx*px + dy*py
|
||||
* denominator = dx^2 + dy^2
|
||||
* t = numerator/denominator
|
||||
*
|
||||
* In CalculateRepeatingGradientParams we know the length of (dx,dy)
|
||||
* is not zero. (This is checked in DrawLinearRepeatingGradient.)
|
||||
*/
|
||||
double px = x - start->x;
|
||||
double py = y - start->y;
|
||||
double numerator = dx * px + dy * py;
|
||||
double denominator = dx * dx + dy * dy;
|
||||
double t = numerator / denominator;
|
||||
|
||||
if (*min_t > t) {
|
||||
*min_t = t;
|
||||
}
|
||||
if (*max_t < t) {
|
||||
*max_t = t;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeat the gradient line such that lines extended perpendicular to the
|
||||
* gradient line at both start and end would completely enclose the drawing
|
||||
* extents.
|
||||
*/
|
||||
static void
|
||||
CalculateRepeatingGradientParams(CGPoint *aStart, CGPoint *aEnd,
|
||||
CGRect aExtents, int *aRepeatCount)
|
||||
{
|
||||
double t_min = 0.;
|
||||
double t_max = 0.;
|
||||
double dx = aEnd->x - aStart->x;
|
||||
double dy = aEnd->y - aStart->y;
|
||||
|
||||
double bounds_x1 = aExtents.origin.x;
|
||||
double bounds_y1 = aExtents.origin.y;
|
||||
double bounds_x2 = aExtents.origin.x + aExtents.size.width;
|
||||
double bounds_y2 = aExtents.origin.y + aExtents.size.height;
|
||||
|
||||
UpdateLinearParametersToIncludePoint(&t_min, &t_max, aStart, dx, dy,
|
||||
bounds_x1, bounds_y1);
|
||||
UpdateLinearParametersToIncludePoint(&t_min, &t_max, aStart, dx, dy,
|
||||
bounds_x2, bounds_y1);
|
||||
UpdateLinearParametersToIncludePoint(&t_min, &t_max, aStart, dx, dy,
|
||||
bounds_x2, bounds_y2);
|
||||
UpdateLinearParametersToIncludePoint(&t_min, &t_max, aStart, dx, dy,
|
||||
bounds_x1, bounds_y2);
|
||||
|
||||
// Move t_min and t_max to the nearest usable integer to try to avoid
|
||||
// subtle variations due to numerical instability, especially accidentally
|
||||
// cutting off a pixel. Extending the gradient repetitions is always safe.
|
||||
t_min = floor (t_min);
|
||||
t_max = ceil (t_max);
|
||||
aEnd->x = aStart->x + dx * t_max;
|
||||
aEnd->y = aStart->y + dy * t_max;
|
||||
aStart->x = aStart->x + dx * t_min;
|
||||
aStart->y = aStart->y + dy * t_min;
|
||||
|
||||
*aRepeatCount = t_max - t_min;
|
||||
}
|
||||
|
||||
static void
|
||||
DrawLinearRepeatingGradient(CGContextRef cg, const LinearGradientPattern &aPattern, const CGRect &aExtents)
|
||||
@ -389,32 +466,12 @@ DrawLinearRepeatingGradient(CGContextRef cg, const LinearGradientPattern &aPatte
|
||||
CGPoint startPoint = { aPattern.mBegin.x, aPattern.mBegin.y };
|
||||
CGPoint endPoint = { aPattern.mEnd.x, aPattern.mEnd.y };
|
||||
|
||||
// extend the gradient line in multiples of the existing length in both
|
||||
// directions until it crosses an edge of the extents box.
|
||||
double xDiff = aPattern.mEnd.x - aPattern.mBegin.x;
|
||||
double yDiff = aPattern.mEnd.y - aPattern.mBegin.y;
|
||||
|
||||
int repeatCount = 1;
|
||||
// if we don't have a line then we can't extend it
|
||||
if (xDiff || yDiff) {
|
||||
while (startPoint.x > aExtents.origin.x
|
||||
&& startPoint.y > aExtents.origin.y
|
||||
&& startPoint.x < (aExtents.origin.x+aExtents.size.width)
|
||||
&& startPoint.y < (aExtents.origin.y+aExtents.size.height))
|
||||
{
|
||||
startPoint.x -= xDiff;
|
||||
startPoint.y -= yDiff;
|
||||
repeatCount++;
|
||||
}
|
||||
while (endPoint.x > aExtents.origin.x
|
||||
&& endPoint.y > aExtents.origin.y
|
||||
&& endPoint.x < (aExtents.origin.x+aExtents.size.width)
|
||||
&& endPoint.y < (aExtents.origin.y+aExtents.size.height))
|
||||
{
|
||||
endPoint.x += xDiff;
|
||||
endPoint.y += yDiff;
|
||||
repeatCount++;
|
||||
}
|
||||
if (aPattern.mEnd.x != aPattern.mBegin.x ||
|
||||
aPattern.mEnd.y != aPattern.mBegin.y) {
|
||||
CalculateRepeatingGradientParams(&startPoint, &endPoint, aExtents,
|
||||
&repeatCount);
|
||||
}
|
||||
|
||||
double scale = 1./repeatCount;
|
||||
|
@ -2494,7 +2494,6 @@ public:
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
virtual EGLImage CreateEGLImageForNativeBuffer(void* buffer) = 0;
|
||||
virtual void DestroyEGLImage(EGLImage image) = 0;
|
||||
virtual EGLImage GetNullEGLImage() = 0;
|
||||
#endif
|
||||
|
||||
virtual already_AddRefed<TextureImage>
|
||||
@ -3579,13 +3578,13 @@ protected:
|
||||
|
||||
private:
|
||||
void Init(GLenum target) {
|
||||
MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D ||
|
||||
target == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
|
||||
mTarget = target;
|
||||
mOldTex = 0;
|
||||
GLenum bindingTarget = (target == LOCAL_GL_TEXTURE_2D) ?
|
||||
LOCAL_GL_TEXTURE_BINDING_2D :
|
||||
LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB;
|
||||
GLenum bindingTarget = (target == LOCAL_GL_TEXTURE_2D) ? LOCAL_GL_TEXTURE_BINDING_2D
|
||||
: (target == LOCAL_GL_TEXTURE_RECTANGLE_ARB) ? LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB
|
||||
: (target == LOCAL_GL_TEXTURE_CUBE_MAP) ? LOCAL_GL_TEXTURE_BINDING_CUBE_MAP
|
||||
: LOCAL_GL_NONE;
|
||||
MOZ_ASSERT(bindingTarget != LOCAL_GL_NONE);
|
||||
mGL->GetUIntegerv(bindingTarget, &mOldTex);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/Util.h"
|
||||
// please add new includes below Qt, otherwise it break Qt build due malloc wrapper conflicts
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
|
||||
@ -13,24 +12,12 @@
|
||||
#include <gdk/gdkx.h>
|
||||
// we're using default display for now
|
||||
#define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow *) aWidget->GetNativeData(NS_NATIVE_WINDOW))
|
||||
#elif defined(MOZ_WIDGET_QT)
|
||||
#include <QtOpenGL/QGLContext>
|
||||
#define GLdouble_defined 1
|
||||
// we're using default display for now
|
||||
#define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)static_cast<QWidget*>(aWidget->GetNativeData(NS_NATIVE_SHELLWIDGET))->winId()
|
||||
#elif defined(MOZ_WIDGET_GONK)
|
||||
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
|
||||
#include "HwcComposer2D.h"
|
||||
#include "libdisplay/GonkDisplay.h"
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_X11)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include "mozilla/X11Util.h"
|
||||
#include "gfxXlibSurface.h"
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID)
|
||||
/* from widget */
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
@ -114,6 +101,7 @@ public:
|
||||
#include "gfxPlatform.h"
|
||||
#include "GLContextProvider.h"
|
||||
#include "GLLibraryEGL.h"
|
||||
#include "TextureImageEGL.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
@ -123,23 +111,13 @@ public:
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
#if defined(MOZ_WIDGET_GONK)
|
||||
static bool gUseBackingSurface = true;
|
||||
#else
|
||||
static bool gUseBackingSurface = false;
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
extern nsIntRect gScreenBounds;
|
||||
#endif
|
||||
|
||||
#define EGL_DISPLAY() sEGLLibrary.Display()
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
static GLLibraryEGL sEGLLibrary;
|
||||
|
||||
#define ADD_ATTR_2(_array, _k, _v) do { \
|
||||
(_array).AppendElement(_k); \
|
||||
(_array).AppendElement(_v); \
|
||||
@ -156,11 +134,6 @@ CreateSurfaceForWindow(nsIWidget *aWidget, EGLConfig config);
|
||||
|
||||
static bool
|
||||
CreateConfig(EGLConfig* aConfig);
|
||||
#ifdef MOZ_X11
|
||||
|
||||
static EGLConfig
|
||||
CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig = nullptr);
|
||||
#endif
|
||||
|
||||
static EGLint gContextAttribs[] = {
|
||||
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
@ -336,13 +309,6 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
char propValue[PROPERTY_VALUE_MAX];
|
||||
property_get("ro.build.version.sdk", propValue, "0");
|
||||
if (atoi(propValue) < 15)
|
||||
gUseBackingSurface = false;
|
||||
#endif
|
||||
|
||||
bool current = MakeCurrent();
|
||||
if (!current) {
|
||||
gfx::LogFailure(NS_LITERAL_CSTRING(
|
||||
@ -444,26 +410,6 @@ public:
|
||||
{
|
||||
sEGLLibrary.fDestroyImage(EGL_DISPLAY(), image);
|
||||
}
|
||||
|
||||
EGLImage GetNullEGLImage() MOZ_OVERRIDE
|
||||
{
|
||||
if (!mNullGraphicBuffer.get()) {
|
||||
mNullGraphicBuffer
|
||||
= new android::GraphicBuffer(
|
||||
1, 1,
|
||||
PIXEL_FORMAT_RGB_565,
|
||||
GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER);
|
||||
EGLint attrs[] = {
|
||||
LOCAL_EGL_NONE, LOCAL_EGL_NONE
|
||||
};
|
||||
mNullEGLImage = sEGLLibrary.fCreateImage(EGL_DISPLAY(),
|
||||
EGL_NO_CONTEXT,
|
||||
LOCAL_EGL_NATIVE_BUFFER_ANDROID,
|
||||
mNullGraphicBuffer->getNativeBuffer(),
|
||||
attrs);
|
||||
}
|
||||
return mNullEGLImage;
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void MakeCurrent_EGLSurface(void* surf) {
|
||||
@ -494,32 +440,7 @@ public:
|
||||
// Assume that EGL has the same problem as WGL does,
|
||||
// where MakeCurrent with an already-current context is
|
||||
// still expensive.
|
||||
#ifndef MOZ_WIDGET_QT
|
||||
if (!mSurface) {
|
||||
// We need to be able to bind NO_SURFACE when we don't
|
||||
// have access to a surface. We won't be drawing to the screen
|
||||
// but we will be able to do things like resource releases.
|
||||
succeeded = sEGLLibrary.fMakeCurrent(EGL_DISPLAY(),
|
||||
EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
if (!succeeded && sEGLLibrary.fGetError() == LOCAL_EGL_CONTEXT_LOST) {
|
||||
mContextLost = true;
|
||||
NS_WARNING("EGL context has been lost.");
|
||||
}
|
||||
NS_ASSERTION(succeeded, "Failed to make GL context current!");
|
||||
return succeeded;
|
||||
}
|
||||
#endif
|
||||
if (aForce || sEGLLibrary.fGetCurrentContext() != mContext) {
|
||||
#ifdef MOZ_WIDGET_QT
|
||||
// Shared Qt GL context need to be informed about context switch
|
||||
if (mSharedContext) {
|
||||
QGLContext* qglCtx = static_cast<QGLContext*>(static_cast<GLContextEGL*>(mSharedContext.get())->mPlatformContext);
|
||||
if (qglCtx) {
|
||||
qglCtx->doneCurrent();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
succeeded = sEGLLibrary.fMakeCurrent(EGL_DISPLAY(),
|
||||
mCurSurface, mCurSurface,
|
||||
mContext);
|
||||
@ -545,13 +466,6 @@ public:
|
||||
return sEGLLibrary.fGetCurrentContext() == mContext;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_QT
|
||||
virtual bool
|
||||
RenewSurface() {
|
||||
/* We don't support renewing on QT because we don't create the surface ourselves */
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
virtual bool
|
||||
RenewSurface() {
|
||||
sEGLLibrary.fMakeCurrent(EGL_DISPLAY(), EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
@ -572,7 +486,6 @@ public:
|
||||
mSurface, mSurface,
|
||||
mContext);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void
|
||||
ReleaseSurface() {
|
||||
@ -687,18 +600,6 @@ protected:
|
||||
bool mShareWithEGLImage;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsRefPtr<HwcComposer2D> mHwc;
|
||||
|
||||
/* mNullEGLImage and mNullGraphicBuffer are a hack to unattach a gralloc buffer
|
||||
* from a texture, which we don't know how to do otherwise (at least in the
|
||||
* TEXTURE_EXTERNAL case --- in the TEXTURE_2D case we could also use TexImage2D).
|
||||
*
|
||||
* So mNullGraphicBuffer will be initialized once to be a 1x1 gralloc buffer,
|
||||
* and mNullEGLImage will be initialized once to be an EGLImage wrapping it.
|
||||
*
|
||||
* This happens in GetNullEGLImage().
|
||||
*/
|
||||
EGLImage mNullEGLImage;
|
||||
android::sp<android::GraphicBuffer> mNullGraphicBuffer;
|
||||
#endif
|
||||
|
||||
// A dummy texture ID that can be used when we need a texture object whose
|
||||
@ -1068,482 +969,6 @@ GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize)
|
||||
return ResizeScreenBuffer(aNewSize);
|
||||
}
|
||||
|
||||
|
||||
static GLContextEGL *
|
||||
GetGlobalContextEGL()
|
||||
{
|
||||
return static_cast<GLContextEGL*>(GLContextProviderEGL::GetGlobalContext());
|
||||
}
|
||||
|
||||
static GLenum
|
||||
GLFormatForImage(gfxImageFormat aFormat)
|
||||
{
|
||||
switch (aFormat) {
|
||||
case gfxImageFormatARGB32:
|
||||
case gfxImageFormatRGB24:
|
||||
// Thebes only supports RGBX, not packed RGB.
|
||||
return LOCAL_GL_RGBA;
|
||||
case gfxImageFormatRGB16_565:
|
||||
return LOCAL_GL_RGB;
|
||||
case gfxImageFormatA8:
|
||||
return LOCAL_GL_LUMINANCE;
|
||||
default:
|
||||
NS_WARNING("Unknown GL format for Image format");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GLenum
|
||||
GLTypeForImage(gfxImageFormat aFormat)
|
||||
{
|
||||
switch (aFormat) {
|
||||
case gfxImageFormatARGB32:
|
||||
case gfxImageFormatRGB24:
|
||||
case gfxImageFormatA8:
|
||||
return LOCAL_GL_UNSIGNED_BYTE;
|
||||
case gfxImageFormatRGB16_565:
|
||||
return LOCAL_GL_UNSIGNED_SHORT_5_6_5;
|
||||
default:
|
||||
NS_WARNING("Unknown GL format for Image format");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
class TextureImageEGL
|
||||
: public TextureImage
|
||||
{
|
||||
public:
|
||||
TextureImageEGL(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
GLenum aWrapMode,
|
||||
ContentType aContentType,
|
||||
GLContext* aContext,
|
||||
Flags aFlags = TextureImage::NoFlags,
|
||||
TextureState aTextureState = Created,
|
||||
TextureImage::ImageFormat aImageFormat = gfxImageFormatUnknown)
|
||||
: TextureImage(aSize, aWrapMode, aContentType, aFlags)
|
||||
, mGLContext(aContext)
|
||||
, mUpdateFormat(aImageFormat)
|
||||
, mEGLImage(nullptr)
|
||||
, mTexture(aTexture)
|
||||
, mSurface(nullptr)
|
||||
, mConfig(nullptr)
|
||||
, mTextureState(aTextureState)
|
||||
, mBound(false)
|
||||
{
|
||||
if (mUpdateFormat == gfxImageFormatUnknown) {
|
||||
mUpdateFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType());
|
||||
}
|
||||
|
||||
if (gUseBackingSurface) {
|
||||
if (mUpdateFormat != gfxImageFormatARGB32) {
|
||||
mTextureFormat = FORMAT_R8G8B8X8;
|
||||
} else {
|
||||
mTextureFormat = FORMAT_R8G8B8A8;
|
||||
}
|
||||
Resize(aSize);
|
||||
} else {
|
||||
if (mUpdateFormat == gfxImageFormatRGB16_565) {
|
||||
mTextureFormat = FORMAT_R8G8B8X8;
|
||||
} else if (mUpdateFormat == gfxImageFormatRGB24) {
|
||||
// RGB24 means really RGBX for Thebes, which means we have to
|
||||
// use the right shader and ignore the uninitialized alpha
|
||||
// value.
|
||||
mTextureFormat = FORMAT_B8G8R8X8;
|
||||
} else {
|
||||
mTextureFormat = FORMAT_B8G8R8A8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~TextureImageEGL()
|
||||
{
|
||||
GLContext *ctx = mGLContext;
|
||||
if (ctx->IsDestroyed() || !ctx->IsOwningThreadCurrent()) {
|
||||
ctx = ctx->GetSharedContext();
|
||||
}
|
||||
|
||||
// If we have a context, then we need to delete the texture;
|
||||
// if we don't have a context (either real or shared),
|
||||
// then they went away when the contex was deleted, because it
|
||||
// was the only one that had access to it.
|
||||
if (ctx && !ctx->IsDestroyed()) {
|
||||
ctx->MakeCurrent();
|
||||
ctx->fDeleteTextures(1, &mTexture);
|
||||
ReleaseTexImage();
|
||||
DestroyEGLSurface();
|
||||
}
|
||||
}
|
||||
|
||||
bool UsingDirectTexture()
|
||||
{
|
||||
return !!mBackingSurface;
|
||||
}
|
||||
|
||||
virtual void GetUpdateRegion(nsIntRegion& aForRegion)
|
||||
{
|
||||
if (mTextureState != Valid) {
|
||||
// if the texture hasn't been initialized yet, force the
|
||||
// client to paint everything
|
||||
aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
|
||||
}
|
||||
|
||||
if (UsingDirectTexture()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We can only draw a rectangle, not subregions due to
|
||||
// the way that our texture upload functions work. If
|
||||
// needed, we /could/ do multiple texture uploads if we have
|
||||
// non-overlapping rects, but that's a tradeoff.
|
||||
aForRegion = nsIntRegion(aForRegion.GetBounds());
|
||||
}
|
||||
|
||||
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion)
|
||||
{
|
||||
NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
|
||||
|
||||
// determine the region the client will need to repaint
|
||||
GetUpdateRegion(aRegion);
|
||||
mUpdateRect = aRegion.GetBounds();
|
||||
|
||||
//printf_stderr("BeginUpdate with updateRect [%d %d %d %d]\n", mUpdateRect.x, mUpdateRect.y, mUpdateRect.width, mUpdateRect.height);
|
||||
if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(mUpdateRect)) {
|
||||
NS_ERROR("update outside of image");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mBackingSurface) {
|
||||
mUpdateSurface = mBackingSurface;
|
||||
return mUpdateSurface;
|
||||
}
|
||||
|
||||
//printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat);
|
||||
|
||||
mUpdateSurface =
|
||||
new gfxImageSurface(gfxIntSize(mUpdateRect.width, mUpdateRect.height),
|
||||
mUpdateFormat);
|
||||
|
||||
mUpdateSurface->SetDeviceOffset(gfxPoint(-mUpdateRect.x, -mUpdateRect.y));
|
||||
|
||||
return mUpdateSurface;
|
||||
}
|
||||
|
||||
virtual void EndUpdate()
|
||||
{
|
||||
NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
|
||||
|
||||
if (mBackingSurface && mUpdateSurface == mBackingSurface) {
|
||||
#ifdef MOZ_X11
|
||||
if (mBackingSurface->GetType() == gfxSurfaceTypeXlib) {
|
||||
FinishX(DefaultXDisplay());
|
||||
}
|
||||
#endif
|
||||
|
||||
mBackingSurface->SetDeviceOffset(gfxPoint(0, 0));
|
||||
mTextureState = Valid;
|
||||
mUpdateSurface = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
//printf_stderr("EndUpdate: slow path");
|
||||
|
||||
// This is the slower path -- we didn't have any way to set up
|
||||
// a fast mapping between our cairo target surface and the GL
|
||||
// texture, so we have to upload data.
|
||||
|
||||
// Undo the device offset that BeginUpdate set; doesn't much
|
||||
// matter for us here, but important if we ever do anything
|
||||
// directly with the surface.
|
||||
mUpdateSurface->SetDeviceOffset(gfxPoint(0, 0));
|
||||
|
||||
nsRefPtr<gfxImageSurface> uploadImage = nullptr;
|
||||
gfxIntSize updateSize(mUpdateRect.width, mUpdateRect.height);
|
||||
|
||||
NS_ASSERTION(mUpdateSurface->GetType() == gfxSurfaceTypeImage &&
|
||||
mUpdateSurface->GetSize() == updateSize,
|
||||
"Upload image isn't an image surface when one is expected, or is wrong size!");
|
||||
|
||||
uploadImage = static_cast<gfxImageSurface*>(mUpdateSurface.get());
|
||||
|
||||
if (!uploadImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
mGLContext->MakeCurrent();
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
if (mTextureState != Valid) {
|
||||
NS_ASSERTION(mUpdateRect.x == 0 && mUpdateRect.y == 0 &&
|
||||
mUpdateRect.Size() == mSize,
|
||||
"Bad initial update on non-created texture!");
|
||||
|
||||
mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
GLFormatForImage(mUpdateFormat),
|
||||
mUpdateRect.width,
|
||||
mUpdateRect.height,
|
||||
0,
|
||||
GLFormatForImage(uploadImage->Format()),
|
||||
GLTypeForImage(uploadImage->Format()),
|
||||
uploadImage->Data());
|
||||
} else {
|
||||
mGLContext->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
mUpdateRect.x,
|
||||
mUpdateRect.y,
|
||||
mUpdateRect.width,
|
||||
mUpdateRect.height,
|
||||
GLFormatForImage(uploadImage->Format()),
|
||||
GLTypeForImage(uploadImage->Format()),
|
||||
uploadImage->Data());
|
||||
}
|
||||
|
||||
mUpdateSurface = nullptr;
|
||||
mTextureState = Valid;
|
||||
return; // mTexture is bound
|
||||
}
|
||||
|
||||
virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
|
||||
{
|
||||
nsIntRect bounds = aRegion.GetBounds();
|
||||
|
||||
nsIntRegion region;
|
||||
if (mTextureState != Valid) {
|
||||
bounds = nsIntRect(0, 0, mSize.width, mSize.height);
|
||||
region = nsIntRegion(bounds);
|
||||
} else {
|
||||
region = aRegion;
|
||||
}
|
||||
|
||||
mTextureFormat =
|
||||
mGLContext->UploadSurfaceToTexture(aSurf,
|
||||
region,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
bounds.TopLeft() + aFrom,
|
||||
false);
|
||||
|
||||
mTextureState = Valid;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void BindTexture(GLenum aTextureUnit)
|
||||
{
|
||||
// Ensure the texture is allocated before it is used.
|
||||
if (mTextureState == Created) {
|
||||
Resize(mSize);
|
||||
}
|
||||
|
||||
mGLContext->fActiveTexture(aTextureUnit);
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
}
|
||||
|
||||
virtual GLuint GetTextureID()
|
||||
{
|
||||
// Ensure the texture is allocated before it is used.
|
||||
if (mTextureState == Created) {
|
||||
Resize(mSize);
|
||||
}
|
||||
return mTexture;
|
||||
};
|
||||
|
||||
virtual bool InUpdate() const { return !!mUpdateSurface; }
|
||||
|
||||
virtual void Resize(const nsIntSize& aSize)
|
||||
{
|
||||
NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
|
||||
|
||||
if (mSize == aSize && mTextureState != Created)
|
||||
return;
|
||||
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
// Try to generate a backin surface first if we have the ability
|
||||
if (gUseBackingSurface) {
|
||||
CreateBackingSurface(gfxIntSize(aSize.width, aSize.height));
|
||||
}
|
||||
|
||||
if (!UsingDirectTexture()) {
|
||||
// If we don't have a backing surface or failed to obtain one,
|
||||
// use the GL Texture failsafe
|
||||
mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
GLFormatForImage(mUpdateFormat),
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
0,
|
||||
GLFormatForImage(mUpdateFormat),
|
||||
GLTypeForImage(mUpdateFormat),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
mTextureState = Allocated;
|
||||
mSize = aSize;
|
||||
}
|
||||
|
||||
bool BindTexImage()
|
||||
{
|
||||
if (mBound && !ReleaseTexImage())
|
||||
return false;
|
||||
|
||||
EGLBoolean success =
|
||||
sEGLLibrary.fBindTexImage(EGL_DISPLAY(),
|
||||
(EGLSurface)mSurface,
|
||||
LOCAL_EGL_BACK_BUFFER);
|
||||
|
||||
if (success == LOCAL_EGL_FALSE)
|
||||
return false;
|
||||
|
||||
mBound = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReleaseTexImage()
|
||||
{
|
||||
if (!mBound)
|
||||
return true;
|
||||
|
||||
EGLBoolean success =
|
||||
sEGLLibrary.fReleaseTexImage(EGL_DISPLAY(),
|
||||
(EGLSurface)mSurface,
|
||||
LOCAL_EGL_BACK_BUFFER);
|
||||
|
||||
if (success == LOCAL_EGL_FALSE)
|
||||
return false;
|
||||
|
||||
mBound = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual already_AddRefed<gfxASurface> GetBackingSurface()
|
||||
{
|
||||
nsRefPtr<gfxASurface> copy = mBackingSurface;
|
||||
return copy.forget();
|
||||
}
|
||||
|
||||
virtual bool CreateEGLSurface(gfxASurface* aSurface)
|
||||
{
|
||||
#ifdef MOZ_X11
|
||||
if (!aSurface) {
|
||||
NS_WARNING("no surface");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aSurface->GetType() != gfxSurfaceTypeXlib) {
|
||||
NS_WARNING("wrong surface type, must be xlib");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mSurface) {
|
||||
return true;
|
||||
}
|
||||
|
||||
EGLSurface surface = CreateEGLSurfaceForXSurface(aSurface, &mConfig);
|
||||
|
||||
if (!surface) {
|
||||
NS_WARNING("couldn't find X config for surface");
|
||||
return false;
|
||||
}
|
||||
|
||||
mSurface = surface;
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void DestroyEGLSurface(void)
|
||||
{
|
||||
if (!mSurface)
|
||||
return;
|
||||
|
||||
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface);
|
||||
mSurface = nullptr;
|
||||
}
|
||||
|
||||
virtual bool CreateBackingSurface(const gfxIntSize& aSize)
|
||||
{
|
||||
ReleaseTexImage();
|
||||
DestroyEGLSurface();
|
||||
mBackingSurface = nullptr;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
Display* dpy = DefaultXDisplay();
|
||||
XRenderPictFormat* renderFMT =
|
||||
gfxXlibSurface::FindRenderFormat(dpy, mUpdateFormat);
|
||||
|
||||
nsRefPtr<gfxXlibSurface> xsurface =
|
||||
gfxXlibSurface::Create(DefaultScreenOfDisplay(dpy),
|
||||
renderFMT,
|
||||
gfxIntSize(aSize.width, aSize.height));
|
||||
|
||||
XSync(dpy, False);
|
||||
mConfig = nullptr;
|
||||
|
||||
if (sEGLLibrary.HasKHRImagePixmap() &&
|
||||
mGLContext->IsExtensionSupported(GLContext::OES_EGL_image))
|
||||
{
|
||||
mEGLImage =
|
||||
sEGLLibrary.fCreateImage(EGL_DISPLAY(),
|
||||
EGL_NO_CONTEXT,
|
||||
LOCAL_EGL_NATIVE_PIXMAP,
|
||||
(EGLClientBuffer)xsurface->XDrawable(),
|
||||
nullptr);
|
||||
|
||||
if (!mEGLImage) {
|
||||
printf_stderr("couldn't create EGL image: ERROR (0x%04x)\n", sEGLLibrary.fGetError());
|
||||
return false;
|
||||
}
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
mGLContext->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, mEGLImage);
|
||||
sEGLLibrary.fDestroyImage(EGL_DISPLAY(), mEGLImage);
|
||||
mEGLImage = nullptr;
|
||||
} else {
|
||||
if (!CreateEGLSurface(xsurface)) {
|
||||
printf_stderr("ProviderEGL Failed create EGL surface: ERROR (0x%04x)\n", sEGLLibrary.fGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BindTexImage()) {
|
||||
printf_stderr("ProviderEGL Failed to bind teximage: ERROR (0x%04x)\n", sEGLLibrary.fGetError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mBackingSurface = xsurface;
|
||||
|
||||
return mBackingSurface != nullptr;
|
||||
#endif
|
||||
|
||||
return mBackingSurface != nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef gfxImageFormat ImageFormat;
|
||||
|
||||
GLContext* mGLContext;
|
||||
|
||||
nsIntRect mUpdateRect;
|
||||
ImageFormat mUpdateFormat;
|
||||
bool mUsingDirectTexture;
|
||||
nsRefPtr<gfxASurface> mBackingSurface;
|
||||
nsRefPtr<gfxASurface> mUpdateSurface;
|
||||
EGLImage mEGLImage;
|
||||
GLuint mTexture;
|
||||
EGLSurface mSurface;
|
||||
EGLConfig mConfig;
|
||||
TextureState mTextureState;
|
||||
|
||||
bool mBound;
|
||||
|
||||
virtual void ApplyFilter()
|
||||
{
|
||||
mGLContext->ApplyFilterToBoundTexture(mFilter);
|
||||
}
|
||||
};
|
||||
|
||||
already_AddRefed<TextureImage>
|
||||
GLContextEGL::CreateTextureImage(const nsIntSize& aSize,
|
||||
TextureImage::ContentType aContentType,
|
||||
@ -1581,8 +1006,6 @@ GLContextEGL::TileGenFunc(const nsIntSize& aSize,
|
||||
return teximage.forget();
|
||||
}
|
||||
|
||||
static nsRefPtr<GLContext> gGlobalContext;
|
||||
|
||||
static const EGLint kEGLConfigAttribsOffscreenPBuffer[] = {
|
||||
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT,
|
||||
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
|
||||
@ -1737,25 +1160,11 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget)
|
||||
if (hasNativeContext && eglContext) {
|
||||
void* platformContext = eglContext;
|
||||
SurfaceCaps caps = SurfaceCaps::Any();
|
||||
#ifdef MOZ_WIDGET_QT
|
||||
int depth = gfxPlatform::GetPlatform()->GetScreenDepth();
|
||||
QGLContext* context = const_cast<QGLContext*>(QGLContext::currentContext());
|
||||
if (context && context->device()) {
|
||||
depth = context->device()->depth();
|
||||
}
|
||||
const QGLFormat& format = context->format();
|
||||
doubleBuffered = format.doubleBuffer();
|
||||
platformContext = context;
|
||||
caps.bpp16 = depth == 16 ? true : false;
|
||||
caps.alpha = format.rgba();
|
||||
caps.depth = format.depth();
|
||||
caps.stencil = format.stencil();
|
||||
#endif
|
||||
EGLConfig config = EGL_NO_CONFIG;
|
||||
EGLSurface surface = sEGLLibrary.fGetCurrentSurface(LOCAL_EGL_DRAW);
|
||||
nsRefPtr<GLContextEGL> glContext =
|
||||
new GLContextEGL(caps,
|
||||
gGlobalContext, false,
|
||||
nullptr, false,
|
||||
config, surface, eglContext);
|
||||
|
||||
if (!glContext->Init())
|
||||
@ -1765,10 +1174,6 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget)
|
||||
glContext->SetIsDoubleBuffered(doubleBuffered);
|
||||
glContext->SetPlatformContext(platformContext);
|
||||
|
||||
if (!gGlobalContext) {
|
||||
gGlobalContext = glContext;
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
@ -1790,11 +1195,10 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GLContextEGL* shareContext = GetGlobalContextEGL();
|
||||
SurfaceCaps caps = SurfaceCaps::Any();
|
||||
nsRefPtr<GLContextEGL> glContext =
|
||||
GLContextEGL::CreateGLContext(caps,
|
||||
shareContext, false,
|
||||
nullptr, false,
|
||||
config, surface);
|
||||
|
||||
if (!glContext) {
|
||||
@ -1841,11 +1245,10 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(const gfxIntSize& size)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GLContextEGL* shareContext = GetGlobalContextEGL();
|
||||
SurfaceCaps dummyCaps = SurfaceCaps::Any();
|
||||
nsRefPtr<GLContextEGL> glContext =
|
||||
GLContextEGL::CreateGLContext(dummyCaps,
|
||||
shareContext, true,
|
||||
nullptr, true,
|
||||
config, surface);
|
||||
if (!glContext) {
|
||||
NS_WARNING("Failed to create GLContext from PBuffer");
|
||||
@ -1862,110 +1265,12 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(const gfxIntSize& size)
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
#ifdef MOZ_X11
|
||||
EGLSurface
|
||||
CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig)
|
||||
{
|
||||
gfxXlibSurface* xsurface = static_cast<gfxXlibSurface*>(aSurface);
|
||||
bool opaque =
|
||||
aSurface->GetContentType() == GFX_CONTENT_COLOR;
|
||||
|
||||
static EGLint pixmap_config_rgb[] = {
|
||||
LOCAL_EGL_TEXTURE_TARGET, LOCAL_EGL_TEXTURE_2D,
|
||||
LOCAL_EGL_TEXTURE_FORMAT, LOCAL_EGL_TEXTURE_RGB,
|
||||
LOCAL_EGL_NONE
|
||||
};
|
||||
|
||||
static EGLint pixmap_config_rgba[] = {
|
||||
LOCAL_EGL_TEXTURE_TARGET, LOCAL_EGL_TEXTURE_2D,
|
||||
LOCAL_EGL_TEXTURE_FORMAT, LOCAL_EGL_TEXTURE_RGBA,
|
||||
LOCAL_EGL_NONE
|
||||
};
|
||||
|
||||
EGLSurface surface = nullptr;
|
||||
if (aConfig && *aConfig) {
|
||||
if (opaque)
|
||||
surface = sEGLLibrary.fCreatePixmapSurface(EGL_DISPLAY(), *aConfig,
|
||||
(EGLNativePixmapType)xsurface->XDrawable(),
|
||||
pixmap_config_rgb);
|
||||
else
|
||||
surface = sEGLLibrary.fCreatePixmapSurface(EGL_DISPLAY(), *aConfig,
|
||||
(EGLNativePixmapType)xsurface->XDrawable(),
|
||||
pixmap_config_rgba);
|
||||
|
||||
if (surface != EGL_NO_SURFACE)
|
||||
return surface;
|
||||
}
|
||||
|
||||
EGLConfig configs[32];
|
||||
int numConfigs = 32;
|
||||
|
||||
static 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
|
||||
};
|
||||
|
||||
if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(),
|
||||
pixmap_config,
|
||||
configs, numConfigs, &numConfigs)
|
||||
|| numConfigs == 0)
|
||||
{
|
||||
NS_WARNING("No EGL Config for pixmap!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < numConfigs; ++i) {
|
||||
if (opaque)
|
||||
surface = sEGLLibrary.fCreatePixmapSurface(EGL_DISPLAY(), configs[i],
|
||||
(EGLNativePixmapType)xsurface->XDrawable(),
|
||||
pixmap_config_rgb);
|
||||
else
|
||||
surface = sEGLLibrary.fCreatePixmapSurface(EGL_DISPLAY(), configs[i],
|
||||
(EGLNativePixmapType)xsurface->XDrawable(),
|
||||
pixmap_config_rgba);
|
||||
|
||||
if (surface != EGL_NO_SURFACE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!surface) {
|
||||
NS_WARNING("Failed to CreatePixmapSurface!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aConfig)
|
||||
*aConfig = configs[i];
|
||||
|
||||
return surface;
|
||||
}
|
||||
#endif
|
||||
|
||||
already_AddRefed<GLContextEGL>
|
||||
GLContextEGL::CreateEGLPixmapOffscreenContext(const gfxIntSize& size)
|
||||
{
|
||||
gfxASurface *thebesSurface = nullptr;
|
||||
EGLNativePixmapType pixmap = 0;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
nsRefPtr<gfxXlibSurface> xsurface =
|
||||
gfxXlibSurface::Create(DefaultScreenOfDisplay(DefaultXDisplay()),
|
||||
gfxXlibSurface::FindRenderFormat(DefaultXDisplay(),
|
||||
gfxImageFormatRGB24),
|
||||
size);
|
||||
|
||||
// XSync required after gfxXlibSurface::Create, otherwise EGL will fail with BadDrawable error
|
||||
XSync(DefaultXDisplay(), False);
|
||||
if (xsurface->CairoStatus() != 0)
|
||||
return nullptr;
|
||||
|
||||
thebesSurface = xsurface;
|
||||
pixmap = (EGLNativePixmapType)xsurface->XDrawable();
|
||||
#endif
|
||||
|
||||
if (!pixmap) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -1973,19 +1278,15 @@ GLContextEGL::CreateEGLPixmapOffscreenContext(const gfxIntSize& size)
|
||||
EGLSurface surface = 0;
|
||||
EGLConfig config = 0;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
surface = CreateEGLSurfaceForXSurface(thebesSurface, &config);
|
||||
#endif
|
||||
if (!config) {
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(surface);
|
||||
|
||||
GLContextEGL* shareContext = GetGlobalContextEGL();
|
||||
SurfaceCaps dummyCaps = SurfaceCaps::Any();
|
||||
nsRefPtr<GLContextEGL> glContext =
|
||||
GLContextEGL::CreateGLContext(dummyCaps,
|
||||
shareContext, true,
|
||||
nullptr, true,
|
||||
config, surface);
|
||||
if (!glContext) {
|
||||
NS_WARNING("Failed to create GLContext from XSurface");
|
||||
@ -2017,18 +1318,11 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& size,
|
||||
|
||||
gfxIntSize dummySize = gfxIntSize(16, 16);
|
||||
nsRefPtr<GLContextEGL> glContext;
|
||||
#if defined(MOZ_X11)
|
||||
glContext = GLContextEGL::CreateEGLPixmapOffscreenContext(dummySize);
|
||||
#else
|
||||
glContext = GLContextEGL::CreateEGLPBufferOffscreenContext(dummySize);
|
||||
#endif
|
||||
|
||||
if (!glContext)
|
||||
return nullptr;
|
||||
|
||||
if (flags & ContextFlagsGlobal)
|
||||
return glContext.forget();
|
||||
|
||||
if (!glContext->InitOffscreen(size, caps))
|
||||
return nullptr;
|
||||
|
||||
@ -2062,7 +1356,6 @@ GLContextProviderEGL::GetGlobalContext(const ContextFlags)
|
||||
void
|
||||
GLContextProviderEGL::Shutdown()
|
||||
{
|
||||
gGlobalContext = nullptr;
|
||||
}
|
||||
|
||||
} /* namespace gl */
|
||||
|
@ -15,6 +15,8 @@
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
GLLibraryEGL sEGLLibrary;
|
||||
|
||||
// should match the order of EGLExtensions, and be null-terminated.
|
||||
static const char *sExtensionNames[] = {
|
||||
"EGL_KHR_image_base",
|
||||
|
@ -530,6 +530,9 @@ private:
|
||||
bool mIsANGLE;
|
||||
};
|
||||
|
||||
extern GLLibraryEGL sEGLLibrary;
|
||||
#define EGL_DISPLAY() sEGLLibrary.Display()
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
||||
|
319
gfx/gl/TextureImageEGL.cpp
Normal file
319
gfx/gl/TextureImageEGL.cpp
Normal file
@ -0,0 +1,319 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "TextureImageEGL.h"
|
||||
#include "GLLibraryEGL.h"
|
||||
#include "GLContext.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
static GLenum
|
||||
GLFormatForImage(gfxImageFormat aFormat)
|
||||
{
|
||||
switch (aFormat) {
|
||||
case gfxImageFormatARGB32:
|
||||
case gfxImageFormatRGB24:
|
||||
// Thebes only supports RGBX, not packed RGB.
|
||||
return LOCAL_GL_RGBA;
|
||||
case gfxImageFormatRGB16_565:
|
||||
return LOCAL_GL_RGB;
|
||||
case gfxImageFormatA8:
|
||||
return LOCAL_GL_LUMINANCE;
|
||||
default:
|
||||
NS_WARNING("Unknown GL format for Image format");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GLenum
|
||||
GLTypeForImage(gfxImageFormat aFormat)
|
||||
{
|
||||
switch (aFormat) {
|
||||
case gfxImageFormatARGB32:
|
||||
case gfxImageFormatRGB24:
|
||||
case gfxImageFormatA8:
|
||||
return LOCAL_GL_UNSIGNED_BYTE;
|
||||
case gfxImageFormatRGB16_565:
|
||||
return LOCAL_GL_UNSIGNED_SHORT_5_6_5;
|
||||
default:
|
||||
NS_WARNING("Unknown GL format for Image format");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
TextureImageEGL::TextureImageEGL(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
GLenum aWrapMode,
|
||||
ContentType aContentType,
|
||||
GLContext* aContext,
|
||||
Flags aFlags,
|
||||
TextureState aTextureState,
|
||||
TextureImage::ImageFormat aImageFormat)
|
||||
: TextureImage(aSize, aWrapMode, aContentType, aFlags)
|
||||
, mGLContext(aContext)
|
||||
, mUpdateFormat(aImageFormat)
|
||||
, mEGLImage(nullptr)
|
||||
, mTexture(aTexture)
|
||||
, mSurface(nullptr)
|
||||
, mConfig(nullptr)
|
||||
, mTextureState(aTextureState)
|
||||
, mBound(false)
|
||||
{
|
||||
if (mUpdateFormat == gfxImageFormatUnknown) {
|
||||
mUpdateFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType());
|
||||
}
|
||||
|
||||
if (mUpdateFormat == gfxImageFormatRGB16_565) {
|
||||
mTextureFormat = gfx::FORMAT_R8G8B8X8;
|
||||
} else if (mUpdateFormat == gfxImageFormatRGB24) {
|
||||
// RGB24 means really RGBX for Thebes, which means we have to
|
||||
// use the right shader and ignore the uninitialized alpha
|
||||
// value.
|
||||
mTextureFormat = gfx::FORMAT_B8G8R8X8;
|
||||
} else {
|
||||
mTextureFormat = gfx::FORMAT_B8G8R8A8;
|
||||
}
|
||||
}
|
||||
|
||||
TextureImageEGL::~TextureImageEGL()
|
||||
{
|
||||
if (mGLContext->IsDestroyed() || !mGLContext->IsOwningThreadCurrent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a context, then we need to delete the texture;
|
||||
// if we don't have a context (either real or shared),
|
||||
// then they went away when the contex was deleted, because it
|
||||
// was the only one that had access to it.
|
||||
mGLContext->MakeCurrent();
|
||||
mGLContext->fDeleteTextures(1, &mTexture);
|
||||
ReleaseTexImage();
|
||||
DestroyEGLSurface();
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageEGL::GetUpdateRegion(nsIntRegion& aForRegion)
|
||||
{
|
||||
if (mTextureState != Valid) {
|
||||
// if the texture hasn't been initialized yet, force the
|
||||
// client to paint everything
|
||||
aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
|
||||
}
|
||||
|
||||
// We can only draw a rectangle, not subregions due to
|
||||
// the way that our texture upload functions work. If
|
||||
// needed, we /could/ do multiple texture uploads if we have
|
||||
// non-overlapping rects, but that's a tradeoff.
|
||||
aForRegion = nsIntRegion(aForRegion.GetBounds());
|
||||
}
|
||||
|
||||
gfxASurface*
|
||||
TextureImageEGL::BeginUpdate(nsIntRegion& aRegion)
|
||||
{
|
||||
NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
|
||||
|
||||
// determine the region the client will need to repaint
|
||||
GetUpdateRegion(aRegion);
|
||||
mUpdateRect = aRegion.GetBounds();
|
||||
|
||||
//printf_stderr("BeginUpdate with updateRect [%d %d %d %d]\n", mUpdateRect.x, mUpdateRect.y, mUpdateRect.width, mUpdateRect.height);
|
||||
if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(mUpdateRect)) {
|
||||
NS_ERROR("update outside of image");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat);
|
||||
|
||||
mUpdateSurface =
|
||||
new gfxImageSurface(gfxIntSize(mUpdateRect.width, mUpdateRect.height),
|
||||
mUpdateFormat);
|
||||
|
||||
mUpdateSurface->SetDeviceOffset(gfxPoint(-mUpdateRect.x, -mUpdateRect.y));
|
||||
|
||||
return mUpdateSurface;
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageEGL::EndUpdate()
|
||||
{
|
||||
NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
|
||||
|
||||
//printf_stderr("EndUpdate: slow path");
|
||||
|
||||
// This is the slower path -- we didn't have any way to set up
|
||||
// a fast mapping between our cairo target surface and the GL
|
||||
// texture, so we have to upload data.
|
||||
|
||||
// Undo the device offset that BeginUpdate set; doesn't much
|
||||
// matter for us here, but important if we ever do anything
|
||||
// directly with the surface.
|
||||
mUpdateSurface->SetDeviceOffset(gfxPoint(0, 0));
|
||||
|
||||
nsRefPtr<gfxImageSurface> uploadImage = nullptr;
|
||||
gfxIntSize updateSize(mUpdateRect.width, mUpdateRect.height);
|
||||
|
||||
NS_ASSERTION(mUpdateSurface->GetType() == gfxSurfaceTypeImage &&
|
||||
mUpdateSurface->GetSize() == updateSize,
|
||||
"Upload image isn't an image surface when one is expected, or is wrong size!");
|
||||
|
||||
uploadImage = static_cast<gfxImageSurface*>(mUpdateSurface.get());
|
||||
|
||||
if (!uploadImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
mGLContext->MakeCurrent();
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
if (mTextureState != Valid) {
|
||||
NS_ASSERTION(mUpdateRect.x == 0 && mUpdateRect.y == 0 &&
|
||||
mUpdateRect.Size() == mSize,
|
||||
"Bad initial update on non-created texture!");
|
||||
|
||||
mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
GLFormatForImage(mUpdateFormat),
|
||||
mUpdateRect.width,
|
||||
mUpdateRect.height,
|
||||
0,
|
||||
GLFormatForImage(uploadImage->Format()),
|
||||
GLTypeForImage(uploadImage->Format()),
|
||||
uploadImage->Data());
|
||||
} else {
|
||||
mGLContext->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
mUpdateRect.x,
|
||||
mUpdateRect.y,
|
||||
mUpdateRect.width,
|
||||
mUpdateRect.height,
|
||||
GLFormatForImage(uploadImage->Format()),
|
||||
GLTypeForImage(uploadImage->Format()),
|
||||
uploadImage->Data());
|
||||
}
|
||||
|
||||
mUpdateSurface = nullptr;
|
||||
mTextureState = Valid;
|
||||
return; // mTexture is bound
|
||||
}
|
||||
|
||||
bool
|
||||
TextureImageEGL::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
|
||||
{
|
||||
nsIntRect bounds = aRegion.GetBounds();
|
||||
|
||||
nsIntRegion region;
|
||||
if (mTextureState != Valid) {
|
||||
bounds = nsIntRect(0, 0, mSize.width, mSize.height);
|
||||
region = nsIntRegion(bounds);
|
||||
} else {
|
||||
region = aRegion;
|
||||
}
|
||||
|
||||
mTextureFormat =
|
||||
mGLContext->UploadSurfaceToTexture(aSurf,
|
||||
region,
|
||||
mTexture,
|
||||
mTextureState == Created,
|
||||
bounds.TopLeft() + aFrom,
|
||||
false);
|
||||
|
||||
mTextureState = Valid;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageEGL::BindTexture(GLenum aTextureUnit)
|
||||
{
|
||||
// Ensure the texture is allocated before it is used.
|
||||
if (mTextureState == Created) {
|
||||
Resize(mSize);
|
||||
}
|
||||
|
||||
mGLContext->fActiveTexture(aTextureUnit);
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageEGL::Resize(const nsIntSize& aSize)
|
||||
{
|
||||
NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
|
||||
|
||||
if (mSize == aSize && mTextureState != Created)
|
||||
return;
|
||||
|
||||
mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
GLFormatForImage(mUpdateFormat),
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
0,
|
||||
GLFormatForImage(mUpdateFormat),
|
||||
GLTypeForImage(mUpdateFormat),
|
||||
nullptr);
|
||||
|
||||
mTextureState = Allocated;
|
||||
mSize = aSize;
|
||||
}
|
||||
|
||||
bool
|
||||
TextureImageEGL::BindTexImage()
|
||||
{
|
||||
if (mBound && !ReleaseTexImage())
|
||||
return false;
|
||||
|
||||
EGLBoolean success =
|
||||
sEGLLibrary.fBindTexImage(EGL_DISPLAY(),
|
||||
(EGLSurface)mSurface,
|
||||
LOCAL_EGL_BACK_BUFFER);
|
||||
|
||||
if (success == LOCAL_EGL_FALSE)
|
||||
return false;
|
||||
|
||||
mBound = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TextureImageEGL::ReleaseTexImage()
|
||||
{
|
||||
if (!mBound)
|
||||
return true;
|
||||
|
||||
EGLBoolean success =
|
||||
sEGLLibrary.fReleaseTexImage(EGL_DISPLAY(),
|
||||
(EGLSurface)mSurface,
|
||||
LOCAL_EGL_BACK_BUFFER);
|
||||
|
||||
if (success == LOCAL_EGL_FALSE)
|
||||
return false;
|
||||
|
||||
mBound = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageEGL::DestroyEGLSurface(void)
|
||||
{
|
||||
if (!mSurface)
|
||||
return;
|
||||
|
||||
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface);
|
||||
mSurface = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageEGL::ApplyFilter()
|
||||
{
|
||||
mGLContext->ApplyFilterToBoundTexture(mFilter);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
86
gfx/gl/TextureImageEGL.h
Normal file
86
gfx/gl/TextureImageEGL.h
Normal file
@ -0,0 +1,86 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef TEXTUREIMAGEEGL_H_
|
||||
#define TEXTUREIMAGEEGL_H_
|
||||
|
||||
#include "GLTextureImage.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
class TextureImageEGL
|
||||
: public TextureImage
|
||||
{
|
||||
public:
|
||||
TextureImageEGL(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
GLenum aWrapMode,
|
||||
ContentType aContentType,
|
||||
GLContext* aContext,
|
||||
Flags aFlags = TextureImage::NoFlags,
|
||||
TextureState aTextureState = Created,
|
||||
TextureImage::ImageFormat aImageFormat = gfxImageFormatUnknown);
|
||||
|
||||
virtual ~TextureImageEGL();
|
||||
|
||||
virtual void GetUpdateRegion(nsIntRegion& aForRegion);
|
||||
|
||||
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
|
||||
|
||||
virtual void EndUpdate();
|
||||
|
||||
virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */);
|
||||
|
||||
virtual void BindTexture(GLenum aTextureUnit);
|
||||
|
||||
virtual GLuint GetTextureID()
|
||||
{
|
||||
// Ensure the texture is allocated before it is used.
|
||||
if (mTextureState == Created) {
|
||||
Resize(mSize);
|
||||
}
|
||||
return mTexture;
|
||||
};
|
||||
|
||||
virtual bool InUpdate() const { return !!mUpdateSurface; }
|
||||
|
||||
virtual void Resize(const nsIntSize& aSize);
|
||||
|
||||
bool BindTexImage();
|
||||
|
||||
bool ReleaseTexImage();
|
||||
|
||||
virtual bool CreateEGLSurface(gfxASurface* aSurface)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void DestroyEGLSurface(void);
|
||||
|
||||
protected:
|
||||
typedef gfxImageFormat ImageFormat;
|
||||
|
||||
GLContext* mGLContext;
|
||||
|
||||
nsIntRect mUpdateRect;
|
||||
ImageFormat mUpdateFormat;
|
||||
nsRefPtr<gfxASurface> mUpdateSurface;
|
||||
EGLImage mEGLImage;
|
||||
GLuint mTexture;
|
||||
EGLSurface mSurface;
|
||||
EGLConfig mConfig;
|
||||
TextureState mTextureState;
|
||||
|
||||
bool mBound;
|
||||
|
||||
virtual void ApplyFilter();
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEXTUREIMAGEEGL_H_
|
@ -102,6 +102,7 @@ CPP_SOURCES += [
|
||||
'SharedSurface.cpp',
|
||||
'GLLibraryEGL.cpp',
|
||||
'SharedSurfaceEGL.cpp',
|
||||
'TextureImageEGL.cpp',
|
||||
'SharedSurfaceGL.cpp',
|
||||
'SurfaceFactory.cpp',
|
||||
'SurfaceStream.cpp',
|
||||
|
@ -705,6 +705,14 @@ CompositorOGL::SetRenderTarget(CompositingRenderTarget *aSurface)
|
||||
CompositingRenderTargetOGL* surface
|
||||
= static_cast<CompositingRenderTargetOGL*>(aSurface);
|
||||
if (mCurrentRenderTarget != surface) {
|
||||
// Restore the scissor rect that was active before we set the current
|
||||
// render target.
|
||||
mGLContext->PopScissorRect();
|
||||
|
||||
// Save the current scissor rect so that we can pop back to it when
|
||||
// changing the render target again.
|
||||
mGLContext->PushScissorRect();
|
||||
|
||||
surface->BindRenderTarget();
|
||||
mCurrentRenderTarget = surface;
|
||||
}
|
||||
@ -828,6 +836,9 @@ CompositorOGL::BeginFrame(const Rect *aClipRectIn, const gfxMatrix& aTransform,
|
||||
mGLContext->fScissor(aClipRectIn->x, aClipRectIn->y, aClipRectIn->width, aClipRectIn->height);
|
||||
}
|
||||
|
||||
// Save the current scissor rect so that SetRenderTarget can pop back to it.
|
||||
mGLContext->PushScissorRect();
|
||||
|
||||
// If the Android compositor is being used, this clear will be done in
|
||||
// DrawWindowUnderlay. Make sure the bits used here match up with those used
|
||||
// in mobile/android/base/gfx/LayerRenderer.java
|
||||
@ -1281,6 +1292,9 @@ CompositorOGL::EndFrame()
|
||||
return;
|
||||
}
|
||||
|
||||
// Restore the scissor rect that we saved in BeginFrame.
|
||||
mGLContext->PopScissorRect();
|
||||
|
||||
mCurrentRenderTarget = nullptr;
|
||||
|
||||
if (sDrawFPS && !mFPS) {
|
||||
|
@ -25,8 +25,8 @@ ifdef IS_COMPONENT
|
||||
$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
|
||||
$(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
|
||||
ifndef NO_COMPONENTS_MANIFEST
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest"
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)"
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest")
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)")
|
||||
endif
|
||||
endif # IS_COMPONENT
|
||||
endif # SHARED_LIBRARY
|
||||
|
@ -1314,8 +1314,8 @@ INSTALL_TARGETS += _XPT_NAME
|
||||
|
||||
ifndef NO_INTERFACES_MANIFEST
|
||||
libs:: $(call mkdir_deps,$(FINAL_TARGET)/components)
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPT_NAME)"
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest"
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPT_NAME)")
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest")
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -1351,7 +1351,7 @@ endif
|
||||
EXTRA_MANIFESTS = $(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))
|
||||
ifneq (,$(EXTRA_MANIFESTS))
|
||||
libs:: $(call mkdir_deps,$(FINAL_TARGET))
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest $(patsubst %,"manifest components/%",$(notdir $(EXTRA_MANIFESTS)))
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest $(patsubst %,"manifest components/%",$(notdir $(EXTRA_MANIFESTS))))
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
@ -2149,70 +2149,8 @@ if test "$ac_cv_header_sys_isa_defs_h" = yes; then
|
||||
AC_DEFINE(JS_HAVE_SYS_ISA_DEFS_H)
|
||||
fi
|
||||
|
||||
dnl Check for uint and uint_t.
|
||||
dnl ========================================================
|
||||
AC_MSG_CHECKING(for uint)
|
||||
AC_CACHE_VAL(ac_cv_uint,
|
||||
[AC_TRY_COMPILE([#include <stdio.h>
|
||||
#include <sys/types.h>],
|
||||
[uint foo = 0;],
|
||||
[ac_cv_uint=true],
|
||||
[ac_cv_uint=false])])
|
||||
if test "$ac_cv_uint" = true ; then
|
||||
AC_DEFINE(HAVE_UINT)
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AC_MSG_CHECKING(for uint_t)
|
||||
AC_CACHE_VAL(ac_cv_uint_t,
|
||||
[AC_TRY_COMPILE([#include <stdio.h>
|
||||
#include <sys/types.h>],
|
||||
[uint_t foo = 0;],
|
||||
[ac_cv_uint_t=true],
|
||||
[ac_cv_uint_t=false])])
|
||||
if test "$ac_cv_uint_t" = true ; then
|
||||
AC_DEFINE(HAVE_UINT_T)
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
dnl On the gcc trunk (as of 2001-02-09) _GNU_SOURCE, and thus __USE_GNU,
|
||||
dnl are defined when compiling C++ but not C. Since the result of this
|
||||
dnl test is used only in C++, do it in C++.
|
||||
AC_LANG_CPLUSPLUS
|
||||
|
||||
AC_MSG_CHECKING(for uname.domainname)
|
||||
AC_CACHE_VAL(ac_cv_have_uname_domainname_field,
|
||||
[AC_TRY_COMPILE([#include <sys/utsname.h>],
|
||||
[ struct utsname *res; char *domain;
|
||||
(void)uname(res); if (res != 0) { domain = res->domainname; } ],
|
||||
[ac_cv_have_uname_domainname_field=true],
|
||||
[ac_cv_have_uname_domainname_field=false])])
|
||||
|
||||
if test "$ac_cv_have_uname_domainname_field" = "true"; then
|
||||
AC_DEFINE(HAVE_UNAME_DOMAINNAME_FIELD)
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(for uname.__domainname)
|
||||
AC_CACHE_VAL(ac_cv_have_uname_us_domainname_field,
|
||||
[AC_TRY_COMPILE([#include <sys/utsname.h>],
|
||||
[ struct utsname *res; char *domain;
|
||||
(void)uname(res); if (res != 0) { domain = res->__domainname; } ],
|
||||
[ac_cv_have_uname_us_domainname_field=true],
|
||||
[ac_cv_have_uname_us_domainname_field=false])])
|
||||
|
||||
if test "$ac_cv_have_uname_us_domainname_field" = "true"; then
|
||||
AC_DEFINE(HAVE_UNAME_US_DOMAINNAME_FIELD)
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
MOZ_CXX11
|
||||
|
||||
dnl Check for .hidden assembler directive and visibility attribute.
|
||||
@ -2628,24 +2566,6 @@ dnl AC_CHECK_LIB(bind, res_ninit, AC_DEFINE(HAVE_RES_NINIT),
|
||||
dnl AC_CHECK_LIB(resolv, res_ninit, AC_DEFINE(HAVE_RES_NINIT)))
|
||||
fi
|
||||
|
||||
AC_LANG_CPLUSPLUS
|
||||
AC_CACHE_CHECK(
|
||||
[for gnu_get_libc_version()],
|
||||
ac_cv_func_gnu_get_libc_version,
|
||||
[AC_TRY_LINK([
|
||||
#ifdef HAVE_GNU_LIBC_VERSION_H
|
||||
#include <gnu/libc-version.h>
|
||||
#endif
|
||||
],
|
||||
[const char *glibc_version = gnu_get_libc_version();],
|
||||
[ac_cv_func_gnu_get_libc_version=yes],
|
||||
[ac_cv_func_gnu_get_libc_version=no]
|
||||
)]
|
||||
)
|
||||
|
||||
if test "$ac_cv_func_gnu_get_libc_version" = "yes"; then
|
||||
AC_DEFINE(HAVE_GNU_GET_LIBC_VERSION)
|
||||
fi
|
||||
AC_LANG_C
|
||||
|
||||
dnl **********************
|
||||
@ -3291,29 +3211,6 @@ if test "$NS_TRACE_MALLOC"; then
|
||||
fi
|
||||
|
||||
if test "$MOZ_MEMORY"; then
|
||||
|
||||
dnl Don't try to run compiler tests on Windows
|
||||
if test "$OS_ARCH" = "WINNT"; then
|
||||
if test -z "$HAVE_64BIT_OS"; then
|
||||
AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 2)
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 3)
|
||||
fi
|
||||
else
|
||||
AC_CHECK_SIZEOF([int *], [4])
|
||||
case "${ac_cv_sizeof_int_p}" in
|
||||
4)
|
||||
AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 2)
|
||||
;;
|
||||
8)
|
||||
AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 3)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([Unexpected pointer size])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
AC_DEFINE(MOZ_MEMORY)
|
||||
if test "x$MOZ_DEBUG" = "x1"; then
|
||||
AC_DEFINE(MOZ_MEMORY_DEBUG)
|
||||
|
@ -420,7 +420,7 @@ class RelocatablePtr : public EncapsulatedPtr<T>
|
||||
|
||||
~RelocatablePtr() {
|
||||
if (this->value)
|
||||
relocate(this->value->runtimeFromMainThread());
|
||||
relocate(this->value->runtimeFromAnyThread());
|
||||
}
|
||||
|
||||
RelocatablePtr<T> &operator=(T *v) {
|
||||
@ -430,7 +430,7 @@ class RelocatablePtr : public EncapsulatedPtr<T>
|
||||
this->value = v;
|
||||
post();
|
||||
} else if (this->value) {
|
||||
JSRuntime *rt = this->value->runtimeFromMainThread();
|
||||
JSRuntime *rt = this->value->runtimeFromAnyThread();
|
||||
this->value = v;
|
||||
relocate(rt);
|
||||
}
|
||||
@ -444,7 +444,7 @@ class RelocatablePtr : public EncapsulatedPtr<T>
|
||||
this->value = v.value;
|
||||
post();
|
||||
} else if (this->value) {
|
||||
JSRuntime *rt = this->value->runtimeFromMainThread();
|
||||
JSRuntime *rt = this->value->runtimeFromAnyThread();
|
||||
this->value = v;
|
||||
relocate(rt);
|
||||
}
|
||||
@ -712,7 +712,7 @@ class HeapValue : public EncapsulatedValue
|
||||
static void writeBarrierPost(const Value &value, Value *addr) {
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (value.isMarkable())
|
||||
shadowRuntimeFromMainThread(value)->gcStoreBufferPtr()->putValue(addr);
|
||||
shadowRuntimeFromAnyThread(value)->gcStoreBufferPtr()->putValue(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -761,7 +761,7 @@ class RelocatableValue : public EncapsulatedValue
|
||||
~RelocatableValue()
|
||||
{
|
||||
if (value.isMarkable())
|
||||
relocate(runtimeFromMainThread(value));
|
||||
relocate(runtimeFromAnyThread(value));
|
||||
}
|
||||
|
||||
RelocatableValue &operator=(const Value &v) {
|
||||
@ -771,7 +771,7 @@ class RelocatableValue : public EncapsulatedValue
|
||||
value = v;
|
||||
post();
|
||||
} else if (value.isMarkable()) {
|
||||
JSRuntime *rt = runtimeFromMainThread(value);
|
||||
JSRuntime *rt = runtimeFromAnyThread(value);
|
||||
relocate(rt);
|
||||
value = v;
|
||||
} else {
|
||||
@ -787,7 +787,7 @@ class RelocatableValue : public EncapsulatedValue
|
||||
value = v.value;
|
||||
post();
|
||||
} else if (value.isMarkable()) {
|
||||
JSRuntime *rt = runtimeFromMainThread(value);
|
||||
JSRuntime *rt = runtimeFromAnyThread(value);
|
||||
relocate(rt);
|
||||
value = v.value;
|
||||
} else {
|
||||
@ -800,7 +800,7 @@ class RelocatableValue : public EncapsulatedValue
|
||||
void post() {
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
JS_ASSERT(value.isMarkable());
|
||||
shadowRuntimeFromMainThread(value)->gcStoreBufferPtr()->putRelocatableValue(&value);
|
||||
shadowRuntimeFromAnyThread(value)->gcStoreBufferPtr()->putRelocatableValue(&value);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -299,7 +299,7 @@ typedef unsigned char uint8_t;
|
||||
typedef unsigned uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef unsigned long long uintmax_t;
|
||||
#if defined(MOZ_MEMORY_SIZEOF_PTR_2POW) && (MOZ_MEMORY_SIZEOF_PTR_2POW == 3)
|
||||
#if defined(_WIN64)
|
||||
typedef long long ssize_t;
|
||||
#else
|
||||
typedef long ssize_t;
|
||||
@ -469,8 +469,8 @@ static const bool isthreaded = true;
|
||||
|
||||
/* Minimum alignment of non-tiny allocations is 2^QUANTUM_2POW_MIN bytes. */
|
||||
# define QUANTUM_2POW_MIN 4
|
||||
#ifdef MOZ_MEMORY_SIZEOF_PTR_2POW
|
||||
# define SIZEOF_PTR_2POW MOZ_MEMORY_SIZEOF_PTR_2POW
|
||||
#if defined(_WIN64) || defined(__LP64__)
|
||||
# define SIZEOF_PTR_2POW 3
|
||||
#else
|
||||
# define SIZEOF_PTR_2POW 2
|
||||
#endif
|
||||
|
@ -42,11 +42,7 @@
|
||||
|
||||
#include "nsNetCID.h"
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
#if !defined(__LP64__)
|
||||
#define BUILD_APPLEFILE_DECODER 1
|
||||
#endif
|
||||
#else
|
||||
#ifndef XP_MACOSX
|
||||
#define BUILD_BINHEX_DECODER 1
|
||||
#endif
|
||||
|
||||
@ -143,15 +139,6 @@ net_NewIncrementalDownload(nsISupports *, const nsIID &, void **);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "nsStreamConverterService.h"
|
||||
|
||||
#ifdef BUILD_APPLEFILE_DECODER
|
||||
#include "nsAppleFileDecoder.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppleFileDecoder)
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "nsMIMEHeaderParamImpl.h"
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMIMEHeaderParamImpl)
|
||||
@ -376,6 +363,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsAndroidNetworkLinkService)
|
||||
nsresult NS_NewFTPDirListingConv(nsFTPDirListingConv** result);
|
||||
#endif
|
||||
|
||||
#include "nsStreamConverterService.h"
|
||||
#include "nsMultiMixedConv.h"
|
||||
#include "nsHTTPCompressConv.h"
|
||||
#include "mozTXTToHTMLConv.h"
|
||||
@ -721,9 +709,6 @@ NS_DEFINE_NAMED_CID(NS_MIMEINPUTSTREAM_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_PROTOCOLPROXYSERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_STREAMCONVERTERSERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_DASHBOARD_CID);
|
||||
#ifdef BUILD_APPLEFILE_DECODER
|
||||
NS_DEFINE_NAMED_CID(NS_APPLEFILEDECODER_CID);
|
||||
#endif
|
||||
#ifdef NECKO_PROTOCOL_ftp
|
||||
NS_DEFINE_NAMED_CID(NS_FTPDIRLISTINGCONVERTER_CID);
|
||||
#endif
|
||||
@ -859,9 +844,6 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
|
||||
{ &kNS_PROTOCOLPROXYSERVICE_CID, true, nullptr, nsProtocolProxyServiceConstructor },
|
||||
{ &kNS_STREAMCONVERTERSERVICE_CID, false, nullptr, CreateNewStreamConvServiceFactory },
|
||||
{ &kNS_DASHBOARD_CID, false, nullptr, mozilla::net::DashboardConstructor },
|
||||
#ifdef BUILD_APPLEFILE_DECODER
|
||||
{ &kNS_APPLEFILEDECODER_CID, false, nullptr, nsAppleFileDecoderConstructor },
|
||||
#endif
|
||||
#ifdef NECKO_PROTOCOL_ftp
|
||||
{ &kNS_FTPDIRLISTINGCONVERTER_CID, false, nullptr, CreateNewFTPDirListingConv },
|
||||
#endif
|
||||
@ -999,9 +981,6 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = {
|
||||
{ NS_PROTOCOLPROXYSERVICE_CONTRACTID, &kNS_PROTOCOLPROXYSERVICE_CID },
|
||||
{ NS_STREAMCONVERTERSERVICE_CONTRACTID, &kNS_STREAMCONVERTERSERVICE_CID },
|
||||
{ NS_DASHBOARD_CONTRACTID, &kNS_DASHBOARD_CID },
|
||||
#ifdef BUILD_APPLEFILE_DECODER
|
||||
{ NS_IAPPLEFILEDECODER_CONTRACTID, &kNS_APPLEFILEDECODER_CID },
|
||||
#endif
|
||||
#ifdef NECKO_PROTOCOL_ftp
|
||||
{ NS_ISTREAMCONVERTER_KEY FTP_TO_INDEX, &kNS_FTPDIRLISTINGCONVERTER_CID },
|
||||
#endif
|
||||
|
@ -13,11 +13,6 @@ XPIDL_SOURCES += [
|
||||
'nsITXTToHTMLConv.idl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
XPIDL_SOURCES += [
|
||||
'nsIAppleFileDecoder.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'necko_strconv'
|
||||
|
||||
MODULE = 'necko'
|
||||
|
@ -1,33 +0,0 @@
|
||||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIOutputStream.idl"
|
||||
|
||||
interface nsIFile;
|
||||
|
||||
%{C++
|
||||
#define NS_APPLEFILEDECODER_CID \
|
||||
{ /* 3a2bb281-64b8-11d5-9daa-bb433143c53c */ \
|
||||
0x3a2bb281, \
|
||||
0x64b8, \
|
||||
0x11d5, \
|
||||
{0x9d, 0xaa, 0xbb, 0x43, 0x31, 0x43, 0xc5, 0x3c} \
|
||||
}
|
||||
|
||||
#define NS_IAPPLEFILEDECODER_CONTRACTID "@mozilla.org/applefiledecoder;1"
|
||||
%}
|
||||
|
||||
|
||||
[scriptable, uuid(3a2bb280-64b8-11d5-9daa-bb433143c53c)]
|
||||
interface nsIAppleFileDecoder : nsIOutputStream {
|
||||
|
||||
/**
|
||||
* Initialize the Apple File Decoder Output stream.
|
||||
*
|
||||
* @param outputStream The output stream which the AppleFile Decoder will write to the data fork.
|
||||
* @param outputFile The output file which the AppleFile Decoder will write to the resource fork.
|
||||
*/
|
||||
void Initialize(in nsIOutputStream outputStream, in nsIFile outputFile);
|
||||
};
|
@ -12,13 +12,6 @@ CPP_SOURCES += [
|
||||
'nsStreamConverterService.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa' and CONFIG['OS_TEST'] != 'x86_64':
|
||||
# nsAppleFileDecoder.cpp has warnings I don't understand.
|
||||
FAIL_ON_WARNINGS = False
|
||||
CPP_SOURCES += [
|
||||
'nsAppleFileDecoder.cpp',
|
||||
]
|
||||
|
||||
LIBRARY_NAME = 'nkconv_s'
|
||||
|
||||
LIBXUL_LIBRARY = True
|
||||
|
@ -1,440 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAppleFileDecoder.h"
|
||||
#include "prmem.h"
|
||||
#include "prnetdb.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsAppleFileDecoder, nsIAppleFileDecoder, nsIOutputStream)
|
||||
|
||||
nsAppleFileDecoder::nsAppleFileDecoder()
|
||||
{
|
||||
m_state = parseHeaders;
|
||||
m_dataBufferLength = 0;
|
||||
m_dataBuffer = (unsigned char*) PR_MALLOC(MAX_BUFFERSIZE);
|
||||
m_entries = nullptr;
|
||||
m_rfRefNum = -1;
|
||||
m_totalDataForkWritten = 0;
|
||||
m_totalResourceForkWritten = 0;
|
||||
m_headerOk = false;
|
||||
|
||||
m_comment[0] = 0;
|
||||
memset(&m_dates, 0, sizeof(m_dates));
|
||||
memset(&m_finderInfo, 0, sizeof(m_dates));
|
||||
memset(&m_finderExtraInfo, 0, sizeof(m_dates));
|
||||
}
|
||||
|
||||
nsAppleFileDecoder::~nsAppleFileDecoder()
|
||||
{
|
||||
if (m_output)
|
||||
Close();
|
||||
|
||||
PR_FREEIF(m_dataBuffer);
|
||||
if (m_entries)
|
||||
delete [] m_entries;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAppleFileDecoder::Initialize(nsIOutputStream *outputStream, nsIFile *outputFile)
|
||||
{
|
||||
m_output = outputStream;
|
||||
|
||||
nsCOMPtr<nsILocalFileMac> macFile = do_QueryInterface(outputFile);
|
||||
bool saveFollowLinks;
|
||||
macFile->GetFollowLinks(&saveFollowLinks);
|
||||
macFile->SetFollowLinks(true);
|
||||
macFile->GetFSSpec(&m_fsFileSpec);
|
||||
macFile->SetFollowLinks(saveFollowLinks);
|
||||
|
||||
m_offset = 0;
|
||||
m_dataForkOffset = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAppleFileDecoder::Close(void)
|
||||
{
|
||||
nsresult rv;
|
||||
rv = m_output->Close();
|
||||
|
||||
int32_t i;
|
||||
|
||||
if (m_rfRefNum != -1)
|
||||
FSClose(m_rfRefNum);
|
||||
|
||||
/* Check if the file is complete and if it's the case, write file attributes */
|
||||
if (m_headerOk)
|
||||
{
|
||||
bool dataOk = true; /* It's ok if the file doesn't have a datafork, therefore set it to true by default. */
|
||||
if (m_headers.magic == APPLESINGLE_MAGIC)
|
||||
{
|
||||
for (i = 0; i < m_headers.entriesCount; i ++)
|
||||
if (ENT_DFORK == m_entries[i].id)
|
||||
{
|
||||
dataOk = (bool)(m_totalDataForkWritten == m_entries[i].length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool resourceOk = FALSE;
|
||||
for (i = 0; i < m_headers.entriesCount; i ++)
|
||||
if (ENT_RFORK == m_entries[i].id)
|
||||
{
|
||||
resourceOk = (bool)(m_totalResourceForkWritten == m_entries[i].length);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dataOk && resourceOk)
|
||||
{
|
||||
HFileInfo *fpb;
|
||||
CInfoPBRec cipbr;
|
||||
|
||||
fpb = (HFileInfo *) &cipbr;
|
||||
fpb->ioVRefNum = m_fsFileSpec.vRefNum;
|
||||
fpb->ioDirID = m_fsFileSpec.parID;
|
||||
fpb->ioNamePtr = m_fsFileSpec.name;
|
||||
fpb->ioFDirIndex = 0;
|
||||
PBGetCatInfoSync(&cipbr);
|
||||
|
||||
/* set finder info */
|
||||
memcpy(&fpb->ioFlFndrInfo, &m_finderInfo, sizeof (FInfo));
|
||||
memcpy(&fpb->ioFlXFndrInfo, &m_finderExtraInfo, sizeof (FXInfo));
|
||||
fpb->ioFlFndrInfo.fdFlags &= 0xfc00; /* clear flags maintained by finder */
|
||||
|
||||
/* set file dates */
|
||||
fpb->ioFlCrDat = m_dates.create - CONVERT_TIME;
|
||||
fpb->ioFlMdDat = m_dates.modify - CONVERT_TIME;
|
||||
fpb->ioFlBkDat = m_dates.backup - CONVERT_TIME;
|
||||
|
||||
/* update file info */
|
||||
fpb->ioDirID = fpb->ioFlParID;
|
||||
PBSetCatInfoSync(&cipbr);
|
||||
|
||||
/* set comment */
|
||||
IOParam vinfo;
|
||||
GetVolParmsInfoBuffer vp;
|
||||
DTPBRec dtp;
|
||||
|
||||
memset((void *) &vinfo, 0, sizeof (vinfo));
|
||||
vinfo.ioVRefNum = fpb->ioVRefNum;
|
||||
vinfo.ioBuffer = (Ptr) &vp;
|
||||
vinfo.ioReqCount = sizeof (vp);
|
||||
if (PBHGetVolParmsSync((HParmBlkPtr) &vinfo) == noErr && ((vp.vMAttrib >> bHasDesktopMgr) & 1))
|
||||
{
|
||||
memset((void *) &dtp, 0, sizeof (dtp));
|
||||
dtp.ioVRefNum = fpb->ioVRefNum;
|
||||
if (PBDTGetPath(&dtp) == noErr)
|
||||
{
|
||||
dtp.ioDTBuffer = (Ptr) &m_comment[1];
|
||||
dtp.ioNamePtr = fpb->ioNamePtr;
|
||||
dtp.ioDirID = fpb->ioDirID;
|
||||
dtp.ioDTReqCount = m_comment[0];
|
||||
if (PBDTSetCommentSync(&dtp) == noErr)
|
||||
PBDTFlushSync(&dtp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* setting m_headerOk to false will prevent us to reprocess the header in case the Close function is called several time*/
|
||||
m_headerOk = false;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAppleFileDecoder::Flush(void)
|
||||
{
|
||||
return m_output->Flush();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAppleFileDecoder::WriteFrom(nsIInputStream *inStr, uint32_t count, uint32_t *_retval)
|
||||
{
|
||||
return m_output->WriteFrom(inStr, count, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAppleFileDecoder::WriteSegments(nsReadSegmentFun reader, void * closure, uint32_t count, uint32_t *_retval)
|
||||
{
|
||||
return m_output->WriteSegments(reader, closure, count, _retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAppleFileDecoder::IsNonBlocking(bool *aNonBlocking)
|
||||
{
|
||||
return m_output->IsNonBlocking(aNonBlocking);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAppleFileDecoder::Write(const char *buffer, uint32_t bufferSize, uint32_t* writeCount)
|
||||
{
|
||||
/* WARNING: to simplify my life, I presume that I should get all appledouble headers in the first block,
|
||||
else I would have to implement a buffer */
|
||||
|
||||
const char * buffPtr = buffer;
|
||||
uint32_t dataCount;
|
||||
int32_t i;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
*writeCount = 0;
|
||||
|
||||
while (bufferSize > 0 && NS_SUCCEEDED(rv))
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case parseHeaders :
|
||||
dataCount = sizeof(ap_header) - m_dataBufferLength;
|
||||
if (dataCount > bufferSize)
|
||||
dataCount = bufferSize;
|
||||
memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount);
|
||||
m_dataBufferLength += dataCount;
|
||||
|
||||
if (m_dataBufferLength == sizeof(ap_header))
|
||||
{
|
||||
memcpy(&m_headers, m_dataBuffer, sizeof(ap_header));
|
||||
m_headers.magic = (int32_t)PR_ntohl((uint32_t)m_headers.magic);
|
||||
m_headers.version = (int32_t)PR_ntohl((uint32_t)m_headers.version);
|
||||
// m_headers.fill is required to be all zeroes; no endian issues
|
||||
m_headers.entriesCount =
|
||||
(int16_t)PR_ntohs((uint16_t)m_headers.entriesCount);
|
||||
|
||||
/* Check header to be sure we are dealing with the right kind of data, else just write it to the data fork. */
|
||||
if ((m_headers.magic == APPLEDOUBLE_MAGIC || m_headers.magic == APPLESINGLE_MAGIC) &&
|
||||
m_headers.version == VERSION && m_headers.entriesCount)
|
||||
{
|
||||
/* Just to be sure, the filler must contains only 0 */
|
||||
for (i = 0; i < 4 && m_headers.fill[i] == 0L; i ++)
|
||||
;
|
||||
if (i == 4)
|
||||
m_state = parseEntries;
|
||||
}
|
||||
m_dataBufferLength = 0;
|
||||
|
||||
if (m_state == parseHeaders)
|
||||
{
|
||||
dataCount = 0;
|
||||
m_state = parseWriteThrough;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case parseEntries :
|
||||
{
|
||||
if (!m_entries)
|
||||
{
|
||||
m_entries = new ap_entry[m_headers.entriesCount];
|
||||
if (!m_entries)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
uint32_t entriesSize = sizeof(ap_entry) * m_headers.entriesCount;
|
||||
dataCount = entriesSize - m_dataBufferLength;
|
||||
if (dataCount > bufferSize)
|
||||
dataCount = bufferSize;
|
||||
memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount);
|
||||
m_dataBufferLength += dataCount;
|
||||
|
||||
if (m_dataBufferLength == entriesSize)
|
||||
{
|
||||
for (i = 0; i < m_headers.entriesCount; i ++)
|
||||
{
|
||||
memcpy(&m_entries[i], &m_dataBuffer[i * sizeof(ap_entry)], sizeof(ap_entry));
|
||||
m_entries[i].id = (int32_t)PR_ntohl((uint32_t)m_entries[i].id);
|
||||
m_entries[i].offset =
|
||||
(int32_t)PR_ntohl((uint32_t)m_entries[i].offset);
|
||||
m_entries[i].length =
|
||||
(int32_t)PR_ntohl((uint32_t)m_entries[i].length);
|
||||
if (m_headers.magic == APPLEDOUBLE_MAGIC)
|
||||
{
|
||||
uint32_t offset = m_entries[i].offset + m_entries[i].length;
|
||||
if (offset > m_dataForkOffset)
|
||||
m_dataForkOffset = offset;
|
||||
}
|
||||
}
|
||||
m_headerOk = true;
|
||||
m_state = parseLookupPart;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case parseLookupPart :
|
||||
/* which part are we parsing? */
|
||||
m_currentPartID = -1;
|
||||
for (i = 0; i < m_headers.entriesCount; i ++)
|
||||
if (m_offset == m_entries[i].offset && m_entries[i].length)
|
||||
{
|
||||
m_currentPartID = m_entries[i].id;
|
||||
m_currentPartLength = m_entries[i].length;
|
||||
m_currentPartCount = 0;
|
||||
|
||||
switch (m_currentPartID)
|
||||
{
|
||||
case ENT_DFORK : m_state = parseDataFork; break;
|
||||
case ENT_RFORK : m_state = parseResourceFork; break;
|
||||
|
||||
case ENT_COMMENT :
|
||||
case ENT_DATES :
|
||||
case ENT_FINFO :
|
||||
m_dataBufferLength = 0;
|
||||
m_state = parsePart;
|
||||
break;
|
||||
|
||||
default : m_state = parseSkipPart; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_currentPartID == -1)
|
||||
{
|
||||
/* maybe is the datafork of an appledouble file? */
|
||||
if (m_offset == m_dataForkOffset)
|
||||
{
|
||||
m_currentPartID = ENT_DFORK;
|
||||
m_currentPartLength = -1;
|
||||
m_currentPartCount = 0;
|
||||
m_state = parseDataFork;
|
||||
}
|
||||
else
|
||||
dataCount = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case parsePart :
|
||||
dataCount = m_currentPartLength - m_dataBufferLength;
|
||||
if (dataCount > bufferSize)
|
||||
dataCount = bufferSize;
|
||||
memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount);
|
||||
m_dataBufferLength += dataCount;
|
||||
|
||||
if (m_dataBufferLength == m_currentPartLength)
|
||||
{
|
||||
switch (m_currentPartID)
|
||||
{
|
||||
case ENT_COMMENT :
|
||||
m_comment[0] = m_currentPartLength > 255 ? 255 : m_currentPartLength;
|
||||
memcpy(&m_comment[1], buffPtr, m_comment[0]);
|
||||
break;
|
||||
case ENT_DATES :
|
||||
if (m_currentPartLength == sizeof(m_dates)) {
|
||||
memcpy(&m_dates, buffPtr, m_currentPartLength);
|
||||
m_dates.create = (int32_t)PR_ntohl((uint32_t)m_dates.create);
|
||||
m_dates.modify = (int32_t)PR_ntohl((uint32_t)m_dates.modify);
|
||||
m_dates.backup = (int32_t)PR_ntohl((uint32_t)m_dates.backup);
|
||||
m_dates.access = (int32_t)PR_ntohl((uint32_t)m_dates.access);
|
||||
}
|
||||
break;
|
||||
case ENT_FINFO :
|
||||
if (m_currentPartLength == (sizeof(m_finderInfo) + sizeof(m_finderExtraInfo)))
|
||||
{
|
||||
memcpy(&m_finderInfo, buffPtr, sizeof(m_finderInfo));
|
||||
// OSType (four character codes) are still integers; swap them.
|
||||
m_finderInfo.fdType =
|
||||
(OSType)PR_ntohl((uint32_t)m_finderInfo.fdType);
|
||||
m_finderInfo.fdCreator =
|
||||
(OSType)PR_ntohl((uint32_t)m_finderInfo.fdCreator);
|
||||
m_finderInfo.fdFlags =
|
||||
(UInt16)PR_ntohs((uint16_t)m_finderInfo.fdFlags);
|
||||
m_finderInfo.fdLocation.v =
|
||||
(short)PR_ntohs((uint16_t)m_finderInfo.fdLocation.v);
|
||||
m_finderInfo.fdLocation.h =
|
||||
(short)PR_ntohs((uint16_t)m_finderInfo.fdLocation.h);
|
||||
m_finderInfo.fdFldr =
|
||||
(SInt16)PR_ntohs((uint16_t)m_finderInfo.fdFldr);
|
||||
|
||||
memcpy(&m_finderExtraInfo, buffPtr + sizeof(m_finderInfo), sizeof(m_finderExtraInfo));
|
||||
m_finderExtraInfo.fdIconID =
|
||||
(SInt16)PR_ntohs((uint16_t)m_finderExtraInfo.fdIconID);
|
||||
m_finderExtraInfo.fdReserved[0] =
|
||||
(SInt16)PR_ntohs((uint16_t)m_finderExtraInfo.fdReserved[0]);
|
||||
m_finderExtraInfo.fdReserved[1] =
|
||||
(SInt16)PR_ntohs((uint16_t)m_finderExtraInfo.fdReserved[1]);
|
||||
m_finderExtraInfo.fdReserved[2] =
|
||||
(SInt16)PR_ntohs((uint16_t)m_finderExtraInfo.fdReserved[2]);
|
||||
// fdScript is a byte
|
||||
// fdXFlags is a byte
|
||||
m_finderExtraInfo.fdComment =
|
||||
(SInt16)PR_ntohs((uint16_t)m_finderExtraInfo.fdComment);
|
||||
m_finderExtraInfo.fdPutAway =
|
||||
(SInt32)PR_ntohl((uint32_t)m_finderExtraInfo.fdPutAway);
|
||||
}
|
||||
break;
|
||||
}
|
||||
m_state = parseLookupPart;
|
||||
}
|
||||
break;
|
||||
|
||||
case parseSkipPart :
|
||||
dataCount = m_currentPartLength - m_currentPartCount;
|
||||
if (dataCount > bufferSize)
|
||||
dataCount = bufferSize;
|
||||
else
|
||||
m_state = parseLookupPart;
|
||||
break;
|
||||
|
||||
case parseDataFork :
|
||||
if (m_headers.magic == APPLEDOUBLE_MAGIC)
|
||||
dataCount = bufferSize;
|
||||
else
|
||||
{
|
||||
dataCount = m_currentPartLength - m_currentPartCount;
|
||||
if (dataCount > bufferSize)
|
||||
dataCount = bufferSize;
|
||||
else
|
||||
m_state = parseLookupPart;
|
||||
}
|
||||
|
||||
if (m_output)
|
||||
{
|
||||
uint32_t writeCount;
|
||||
rv = m_output->Write((const char *)buffPtr, dataCount, &writeCount);
|
||||
if (dataCount != writeCount)
|
||||
rv = NS_ERROR_FAILURE;
|
||||
m_totalDataForkWritten += dataCount;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case parseResourceFork :
|
||||
{
|
||||
dataCount = m_currentPartLength - m_currentPartCount;
|
||||
if (dataCount > bufferSize)
|
||||
dataCount = bufferSize;
|
||||
else
|
||||
m_state = parseLookupPart;
|
||||
|
||||
if (m_rfRefNum == -1)
|
||||
{
|
||||
if (noErr != FSpOpenRF(&m_fsFileSpec, fsWrPerm, &m_rfRefNum))
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
long count = dataCount;
|
||||
if (noErr != FSWrite(m_rfRefNum, &count, buffPtr) || count != dataCount)
|
||||
return NS_ERROR_FAILURE;
|
||||
m_totalResourceForkWritten += dataCount;
|
||||
}
|
||||
break;
|
||||
|
||||
case parseWriteThrough :
|
||||
dataCount = bufferSize;
|
||||
if (m_output)
|
||||
{
|
||||
uint32_t writeCount;
|
||||
rv = m_output->Write((const char *)buffPtr, dataCount, &writeCount);
|
||||
if (dataCount != writeCount)
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (dataCount)
|
||||
{
|
||||
*writeCount += dataCount;
|
||||
bufferSize -= dataCount;
|
||||
buffPtr += dataCount;
|
||||
m_currentPartCount += dataCount;
|
||||
m_offset += dataCount;
|
||||
dataCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsAppleFileDecoder_h__
|
||||
#define nsAppleFileDecoder_h__
|
||||
|
||||
#include "nsIAppleFileDecoder.h"
|
||||
#include "nsILocalFileMac.h"
|
||||
|
||||
/*
|
||||
** applefile definitions used
|
||||
*/
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=mac68k
|
||||
#endif
|
||||
|
||||
#define APPLESINGLE_MAGIC 0x00051600L
|
||||
#define APPLEDOUBLE_MAGIC 0x00051607L
|
||||
#define VERSION 0x00020000
|
||||
|
||||
#define NUM_ENTRIES 6
|
||||
|
||||
#define ENT_DFORK 1L
|
||||
#define ENT_RFORK 2L
|
||||
#define ENT_NAME 3L
|
||||
#define ENT_COMMENT 4L
|
||||
#define ENT_DATES 8L
|
||||
#define ENT_FINFO 9L
|
||||
|
||||
#define CONVERT_TIME 1265437696L
|
||||
|
||||
/*
|
||||
** data type used in the header decoder.
|
||||
*/
|
||||
typedef struct ap_header
|
||||
{
|
||||
int32_t magic;
|
||||
int32_t version;
|
||||
int32_t fill[4];
|
||||
int16_t entriesCount;
|
||||
|
||||
} ap_header;
|
||||
|
||||
typedef struct ap_entry
|
||||
{
|
||||
int32_t id;
|
||||
int32_t offset;
|
||||
int32_t length;
|
||||
|
||||
} ap_entry;
|
||||
|
||||
typedef struct ap_dates
|
||||
{
|
||||
int32_t create, modify, backup, access;
|
||||
|
||||
} ap_dates;
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=reset
|
||||
#endif
|
||||
|
||||
/*
|
||||
**Error codes
|
||||
*/
|
||||
enum {
|
||||
errADNotEnoughData = -12099,
|
||||
errADNotSupported,
|
||||
errADBadVersion
|
||||
};
|
||||
|
||||
|
||||
class nsAppleFileDecoder : public nsIAppleFileDecoder
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOUTPUTSTREAM
|
||||
NS_DECL_NSIAPPLEFILEDECODER
|
||||
|
||||
nsAppleFileDecoder();
|
||||
virtual ~nsAppleFileDecoder();
|
||||
|
||||
private:
|
||||
#define MAX_BUFFERSIZE 1024
|
||||
enum ParserState {parseHeaders, parseEntries, parseLookupPart, parsePart, parseSkipPart,
|
||||
parseDataFork, parseResourceFork, parseWriteThrough};
|
||||
|
||||
nsCOMPtr<nsIOutputStream> m_output;
|
||||
FSSpec m_fsFileSpec;
|
||||
SInt16 m_rfRefNum;
|
||||
|
||||
unsigned char * m_dataBuffer;
|
||||
int32_t m_dataBufferLength;
|
||||
ParserState m_state;
|
||||
ap_header m_headers;
|
||||
ap_entry * m_entries;
|
||||
int32_t m_offset;
|
||||
int32_t m_dataForkOffset;
|
||||
int32_t m_totalDataForkWritten;
|
||||
int32_t m_totalResourceForkWritten;
|
||||
bool m_headerOk;
|
||||
|
||||
int32_t m_currentPartID;
|
||||
int32_t m_currentPartLength;
|
||||
int32_t m_currentPartCount;
|
||||
|
||||
Str255 m_comment;
|
||||
ap_dates m_dates;
|
||||
FInfo m_finderInfo;
|
||||
FXInfo m_finderExtraInfo;
|
||||
};
|
||||
|
||||
#endif
|
@ -4,6 +4,7 @@
|
||||
|
||||
test_dirs := \
|
||||
mozbuild/mozbuild/test \
|
||||
mozbuild/mozbuild/test/action \
|
||||
mozbuild/mozbuild/test/backend \
|
||||
mozbuild/mozbuild/test/controller \
|
||||
mozbuild/mozbuild/test/compilation \
|
||||
|
@ -1,42 +1,49 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
'''A generic script to add entries to a file
|
||||
if the entry does not already exist.
|
||||
|
||||
Usage: buildlist.py <filename> <entry> [<entry> ...]
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
import os
|
||||
from utils import lockFile
|
||||
|
||||
def addEntriesToListFile(listFile, entries):
|
||||
"""Given a file |listFile| containing one entry per line,
|
||||
add each entry in |entries| to the file, unless it is already
|
||||
present."""
|
||||
lock = lockFile(listFile + ".lck")
|
||||
try:
|
||||
if os.path.exists(listFile):
|
||||
f = open(listFile)
|
||||
existing = set(x.strip() for x in f.readlines())
|
||||
f.close()
|
||||
else:
|
||||
existing = set()
|
||||
f = open(listFile, 'a')
|
||||
for e in entries:
|
||||
if e not in existing:
|
||||
f.write("{0}\n".format(e))
|
||||
existing.add(e)
|
||||
f.close()
|
||||
finally:
|
||||
lock = None
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: buildlist.py <list file> <entry> [<entry> ...]",
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
addEntriesToListFile(sys.argv[1], sys.argv[2:])
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
'''A generic script to add entries to a file
|
||||
if the entry does not already exist.
|
||||
|
||||
Usage: buildlist.py <filename> <entry> [<entry> ...]
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
from mozbuild.util import lock_file
|
||||
|
||||
def addEntriesToListFile(listFile, entries):
|
||||
"""Given a file |listFile| containing one entry per line,
|
||||
add each entry in |entries| to the file, unless it is already
|
||||
present."""
|
||||
lock = lock_file(listFile + ".lck")
|
||||
try:
|
||||
if os.path.exists(listFile):
|
||||
f = open(listFile)
|
||||
existing = set(x.strip() for x in f.readlines())
|
||||
f.close()
|
||||
else:
|
||||
existing = set()
|
||||
f = open(listFile, 'a')
|
||||
for e in entries:
|
||||
if e not in existing:
|
||||
f.write("{0}\n".format(e))
|
||||
existing.add(e)
|
||||
f.close()
|
||||
finally:
|
||||
lock = None
|
||||
|
||||
|
||||
def main(args):
|
||||
if len(args) < 2:
|
||||
print("Usage: buildlist.py <list file> <entry> [<entry> ...]",
|
||||
file=sys.stderr)
|
||||
return 1
|
||||
|
||||
return addEntriesToListFile(args[0], args[1:])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
@ -1,3 +1,7 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import unittest
|
||||
|
||||
import os, sys, os.path, time
|
||||
@ -5,7 +9,8 @@ from tempfile import mkdtemp
|
||||
from shutil import rmtree
|
||||
import mozunit
|
||||
|
||||
from buildlist import addEntriesToListFile
|
||||
from mozbuild.action.buildlist import addEntriesToListFile
|
||||
|
||||
|
||||
class TestBuildList(unittest.TestCase):
|
||||
"""
|
@ -11,10 +11,13 @@ import copy
|
||||
import errno
|
||||
import hashlib
|
||||
import os
|
||||
import stat
|
||||
import sys
|
||||
import time
|
||||
|
||||
from StringIO import StringIO
|
||||
|
||||
|
||||
if sys.version_info[0] == 3:
|
||||
str_type = str
|
||||
else:
|
||||
@ -370,3 +373,120 @@ class HierarchicalStringList(object):
|
||||
if not isinstance(v, str_type):
|
||||
raise ValueError(
|
||||
'Expected a list of strings, not an element of %s' % type(v))
|
||||
|
||||
|
||||
class LockFile(object):
|
||||
"""LockFile is used by the lock_file method to hold the lock.
|
||||
|
||||
This object should not be used directly, but only through
|
||||
the lock_file method below.
|
||||
"""
|
||||
|
||||
def __init__(self, lockfile):
|
||||
self.lockfile = lockfile
|
||||
|
||||
def __del__(self):
|
||||
while True:
|
||||
try:
|
||||
os.remove(self.lockfile)
|
||||
break
|
||||
except OSError as e:
|
||||
if e.errno == errno.EACCES:
|
||||
# Another process probably has the file open, we'll retry.
|
||||
# Just a short sleep since we want to drop the lock ASAP
|
||||
# (but we need to let some other process close the file
|
||||
# first).
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
# Re-raise unknown errors
|
||||
raise
|
||||
|
||||
|
||||
def lock_file(lockfile, max_wait = 600):
|
||||
"""Create and hold a lockfile of the given name, with the given timeout.
|
||||
|
||||
To release the lock, delete the returned object.
|
||||
"""
|
||||
|
||||
# FUTURE This function and object could be written as a context manager.
|
||||
|
||||
while True:
|
||||
try:
|
||||
fd = os.open(lockfile, os.O_EXCL | os.O_RDWR | os.O_CREAT)
|
||||
# We created the lockfile, so we're the owner
|
||||
break
|
||||
except OSError as e:
|
||||
if (e.errno == errno.EEXIST or
|
||||
(sys.platform == "win32" and e.errno == errno.EACCES)):
|
||||
pass
|
||||
else:
|
||||
# Should not occur
|
||||
raise
|
||||
|
||||
try:
|
||||
# The lock file exists, try to stat it to get its age
|
||||
# and read its contents to report the owner PID
|
||||
f = open(lockfile, 'r')
|
||||
s = os.stat(lockfile)
|
||||
except EnvironmentError as e:
|
||||
if e.errno == errno.ENOENT or e.errno == errno.EACCES:
|
||||
# We didn't create the lockfile, so it did exist, but it's
|
||||
# gone now. Just try again
|
||||
continue
|
||||
|
||||
raise Exception('{0} exists but stat() failed: {1}'.format(
|
||||
lockfile, e.strerror))
|
||||
|
||||
# We didn't create the lockfile and it's still there, check
|
||||
# its age
|
||||
now = int(time.time())
|
||||
if now - s[stat.ST_MTIME] > max_wait:
|
||||
pid = f.readline().rstrip()
|
||||
raise Exception('{0} has been locked for more than '
|
||||
'{1} seconds (PID {2})'.format(lockfile, max_wait, pid))
|
||||
|
||||
# It's not been locked too long, wait a while and retry
|
||||
f.close()
|
||||
time.sleep(1)
|
||||
|
||||
# if we get here. we have the lockfile. Convert the os.open file
|
||||
# descriptor into a Python file object and record our PID in it
|
||||
f = os.fdopen(fd, 'w')
|
||||
f.write('{0}\n'.format(os.getpid()))
|
||||
f.close()
|
||||
|
||||
return LockFile(lockfile)
|
||||
|
||||
|
||||
class PushbackIter(object):
|
||||
'''Utility iterator that can deal with pushed back elements.
|
||||
|
||||
This behaves like a regular iterable, just that you can call
|
||||
iter.pushback(item) to get the given item as next item in the
|
||||
iteration.
|
||||
'''
|
||||
def __init__(self, iterable):
|
||||
self.it = iter(iterable)
|
||||
self.pushed_back = []
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __nonzero__(self):
|
||||
if self.pushed_back:
|
||||
return True
|
||||
|
||||
try:
|
||||
self.pushed_back.insert(0, self.it.next())
|
||||
except StopIteration:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def next(self):
|
||||
if self.pushed_back:
|
||||
return self.pushed_back.pop()
|
||||
return self.it.next()
|
||||
|
||||
def pushback(self, item):
|
||||
self.pushed_back.append(item)
|
||||
|
@ -110,10 +110,8 @@ nsUserInfo::GetDomain(char * *aDomain)
|
||||
return rv;
|
||||
}
|
||||
|
||||
#if defined(HAVE_UNAME_DOMAINNAME_FIELD)
|
||||
#if defined(__linux__)
|
||||
domainname = buf.domainname;
|
||||
#elif defined(HAVE_UNAME_US_DOMAINNAME_FIELD)
|
||||
domainname = buf.__domainname;
|
||||
#endif
|
||||
|
||||
if (domainname && domainname[0]) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "mozilla/NullPtr.h"
|
||||
|
||||
using std::string;
|
||||
using std::istream;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "mozilla/NullPtr.h"
|
||||
#include "common/linux/http_upload.h"
|
||||
#include "crashreporter.h"
|
||||
#include "crashreporter_gtk_common.h"
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <cctype>
|
||||
|
||||
#include "mozilla/NullPtr.h"
|
||||
#include "crashreporter.h"
|
||||
#include "crashreporter_gtk_common.h"
|
||||
|
||||
|
@ -70,9 +70,6 @@
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#include "nsILocalFileMac.h"
|
||||
#ifndef __LP64__
|
||||
#include "nsIAppleFileDecoder.h"
|
||||
#endif
|
||||
#elif defined(XP_OS2)
|
||||
#include "nsILocalFileOS2.h"
|
||||
#endif
|
||||
|
@ -22,7 +22,7 @@ DEFINES += -DMOZILLA_OFFICIAL
|
||||
endif
|
||||
|
||||
libs:: $(call mkdir_deps,$(FINAL_TARGET))
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "resource webapprt ./"
|
||||
$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "resource webapprt ./")
|
||||
|
||||
GRE_MILESTONE := $(shell tail -n 1 $(topsrcdir)/config/milestone.txt 2>/dev/null || tail -1 $(topsrcdir)/config/milestone.txt)
|
||||
GRE_BUILDID := $(shell cat $(DEPTH)/config/buildid)
|
||||
|
@ -12,7 +12,7 @@
|
||||
* implementation of this interface for non-Windows systems, for testing and
|
||||
* development purposes only.
|
||||
*/
|
||||
[scriptable, uuid(fa6750a2-f0fe-411c-af23-1cd6d2fdeceb)]
|
||||
[scriptable, uuid(25524bde-8b30-4b49-8d67-7070c790aada)]
|
||||
interface nsIWinMetroUtils : nsISupports
|
||||
{
|
||||
/* return constants for the handPreference property */
|
||||
@ -49,7 +49,7 @@ interface nsIWinMetroUtils : nsISupports
|
||||
/**
|
||||
* Displays a native Windows 8 toast.
|
||||
*/
|
||||
void showNativeToast(in AString aTitle, in AString aMessage, in AString anImage);
|
||||
void showNativeToast(in AString aTitle, in AString aMessage, in AString anImage, in AString aCookie);
|
||||
|
||||
/**
|
||||
* Secondary tiles are a Windows 8 specific feature for pinning new tiles
|
||||
|
@ -16,8 +16,16 @@ using namespace mozilla;
|
||||
using namespace ABI::Windows::UI::Notifications;
|
||||
|
||||
typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_IInspectable_t ToastActivationHandler;
|
||||
typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_Windows__CUI__CNotifications__CToastDismissedEventArgs ToastDismissHandler;
|
||||
|
||||
void
|
||||
ToastNotificationHandler::DisplayNotification(HSTRING title,
|
||||
HSTRING msg,
|
||||
HSTRING imagePath,
|
||||
const nsAString& aCookie)
|
||||
{
|
||||
mCookie = aCookie;
|
||||
|
||||
void ToastNotificationHandler::DisplayNotification(HSTRING title, HSTRING msg, HSTRING imagePath) {
|
||||
ComPtr<IToastNotificationManagerStatics> toastNotificationManagerStatics;
|
||||
AssertHRESULT(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(),
|
||||
toastNotificationManagerStatics.GetAddressOf()));
|
||||
@ -57,10 +65,15 @@ void ToastNotificationHandler::DisplayNotification(HSTRING title, HSTRING msg, H
|
||||
EventRegistrationToken activatedToken;
|
||||
AssertHRESULT(notification->add_Activated(Callback<ToastActivationHandler>(this,
|
||||
&ToastNotificationHandler::OnActivate).Get(), &activatedToken));
|
||||
EventRegistrationToken dismissedToken;
|
||||
AssertHRESULT(notification->add_Dismissed(Callback<ToastDismissHandler>(this,
|
||||
&ToastNotificationHandler::OnDismiss).Get(), &dismissedToken));
|
||||
|
||||
ComPtr<IToastNotifier> notifier;
|
||||
toastNotificationManagerStatics->CreateToastNotifier(¬ifier);
|
||||
notifier->Show(notification.Get());
|
||||
|
||||
MetroUtils::FireObserver("metro_native_toast_shown", mCookie.get());
|
||||
}
|
||||
|
||||
void ToastNotificationHandler::SetNodeValueString(HSTRING inputString, ComPtr<IXmlNode> node, ComPtr<IXmlDocument> xml) {
|
||||
@ -73,6 +86,14 @@ void ToastNotificationHandler::SetNodeValueString(HSTRING inputString, ComPtr<IX
|
||||
}
|
||||
|
||||
HRESULT ToastNotificationHandler::OnActivate(IToastNotification *notification, IInspectable *inspectable) {
|
||||
MetroUtils::FireObserver("metro_native_toast_clicked");
|
||||
MetroUtils::FireObserver("metro_native_toast_clicked", mCookie.get());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
ToastNotificationHandler::OnDismiss(IToastNotification *notification,
|
||||
IToastDismissedEventArgs* aArgs)
|
||||
{
|
||||
MetroUtils::FireObserver("metro_native_toast_dismissed", mCookie.get());
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -8,11 +8,13 @@
|
||||
#include <windows.ui.notifications.h>
|
||||
#include <windows.data.xml.dom.h>
|
||||
#include "mozwrlbase.h"
|
||||
#include "nsString.h"
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
class ToastNotificationHandler {
|
||||
typedef ABI::Windows::UI::Notifications::IToastNotification IToastNotification;
|
||||
typedef ABI::Windows::UI::Notifications::IToastDismissedEventArgs IToastDismissedEventArgs;
|
||||
typedef ABI::Windows::Data::Xml::Dom::IXmlNode IXmlNode;
|
||||
typedef ABI::Windows::Data::Xml::Dom::IXmlDocument IXmlDocument;
|
||||
|
||||
@ -21,6 +23,11 @@ class ToastNotificationHandler {
|
||||
ToastNotificationHandler() {};
|
||||
~ToastNotificationHandler() {};
|
||||
|
||||
void DisplayNotification(HSTRING title, HSTRING msg, HSTRING imagePath);
|
||||
void DisplayNotification(HSTRING title, HSTRING msg, HSTRING imagePath, const nsAString& aCookie);
|
||||
HRESULT OnActivate(IToastNotification *notification, IInspectable *inspectable);
|
||||
HRESULT OnDismiss(IToastNotification *notification,
|
||||
IToastDismissedEventArgs* aArgs);
|
||||
|
||||
private:
|
||||
nsString mCookie;
|
||||
};
|
||||
|
@ -345,7 +345,8 @@ nsWinMetroUtils::LaunchInDesktop(const nsAString &aPath, const nsAString &aArgum
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWinMetroUtils::ShowNativeToast(const nsAString &aTitle,
|
||||
const nsAString &aMessage, const nsAString &anImage)
|
||||
const nsAString &aMessage, const nsAString &anImage,
|
||||
const nsAString &aCookie)
|
||||
{
|
||||
// Firefox is in the foreground, no need for a notification.
|
||||
if (::GetActiveWindow() == ::GetForegroundWindow()) {
|
||||
@ -358,7 +359,7 @@ nsWinMetroUtils::ShowNativeToast(const nsAString &aTitle,
|
||||
HSTRING title = HStringReference(aTitle.BeginReading()).Get();
|
||||
HSTRING msg = HStringReference(aMessage.BeginReading()).Get();
|
||||
HSTRING imagePath = HStringReference(anImage.BeginReading()).Get();
|
||||
notification_handler->DisplayNotification(title, msg, imagePath);
|
||||
notification_handler->DisplayNotification(title, msg, imagePath, aCookie);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ static const uint32_t CPU_TYPE = CPU_TYPE_POWERPC64;
|
||||
#error Unsupported CPU type
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_64BIT_OS
|
||||
#ifdef __LP64__
|
||||
#undef LC_SEGMENT
|
||||
#define LC_SEGMENT LC_SEGMENT_64
|
||||
#undef MH_MAGIC
|
||||
|
@ -6,3 +6,6 @@ export::
|
||||
$(call SUBMAKE,xpidl-parser,$(DEPTH)/xpcom/idl-parser)
|
||||
$(call py_action,process_install_manifest,$(DIST)/idl $(DEPTH)/_build_manifests/install/dist_idl)
|
||||
$(call SUBMAKE,xpidl,$(DEPTH)/config/makefiles/xpidl)
|
||||
|
||||
clean clobber realclean clobber_all distclean::
|
||||
$(call SUBMAKE,$@,$(DEPTH)/config/makefiles/xpidl)
|
||||
|
Loading…
Reference in New Issue
Block a user