mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 996266 - Fall back from failed WebGL context creation attribs. - r=kamidphish,bjacob
This commit is contained in:
parent
fd5e2abf5a
commit
9451a4fa01
@ -72,6 +72,8 @@
|
|||||||
#include "mozilla/layers/ShadowLayers.h"
|
#include "mozilla/layers/ShadowLayers.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
using namespace mozilla::gfx;
|
using namespace mozilla::gfx;
|
||||||
@ -435,12 +437,10 @@ WebGLContext::SetContextOptions(JSContext* aCx, JS::Handle<JS::Value> aOptions)
|
|||||||
newOpts.premultipliedAlpha = attributes.mPremultipliedAlpha;
|
newOpts.premultipliedAlpha = attributes.mPremultipliedAlpha;
|
||||||
newOpts.antialias = attributes.mAntialias;
|
newOpts.antialias = attributes.mAntialias;
|
||||||
newOpts.preserveDrawingBuffer = attributes.mPreserveDrawingBuffer;
|
newOpts.preserveDrawingBuffer = attributes.mPreserveDrawingBuffer;
|
||||||
if (attributes.mAlpha.WasPassed()) {
|
|
||||||
newOpts.alpha = attributes.mAlpha.Value();
|
|
||||||
}
|
|
||||||
|
|
||||||
// enforce that if stencil is specified, we also give back depth
|
if (attributes.mAlpha.WasPassed()) {
|
||||||
newOpts.depth |= newOpts.stencil;
|
newOpts.alpha = attributes.mAlpha.Value();
|
||||||
|
}
|
||||||
|
|
||||||
// Don't do antialiasing if we've disabled MSAA.
|
// Don't do antialiasing if we've disabled MSAA.
|
||||||
if (!gfxPrefs::MSAALevel()) {
|
if (!gfxPrefs::MSAALevel()) {
|
||||||
@ -471,36 +471,333 @@ WebGLContext::SetContextOptions(JSContext* aCx, JS::Handle<JS::Value> aOptions)
|
|||||||
int32_t
|
int32_t
|
||||||
WebGLContext::GetWidth() const
|
WebGLContext::GetWidth() const
|
||||||
{
|
{
|
||||||
return mWidth;
|
return mWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
WebGLContext::GetHeight() const
|
WebGLContext::GetHeight() const
|
||||||
{
|
{
|
||||||
return mHeight;
|
return mHeight;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* So there are a number of points of failure here. We might fail based
|
||||||
|
* on EGL vs. WGL, or we might fail to alloc a too-large size, or we
|
||||||
|
* might not be able to create a context with a certain combo of context
|
||||||
|
* creation attribs.
|
||||||
|
*
|
||||||
|
* We don't want to test the complete fallback matrix. (for now, at
|
||||||
|
* least) Instead, attempt creation in this order:
|
||||||
|
* 1. By platform API. (e.g. EGL vs. WGL)
|
||||||
|
* 2. By context creation attribs.
|
||||||
|
* 3. By size.
|
||||||
|
*
|
||||||
|
* That is, try to create headless contexts based on the platform API.
|
||||||
|
* Next, create dummy-sized backbuffers for the contexts with the right
|
||||||
|
* caps. Finally, resize the backbuffer to an acceptable size given the
|
||||||
|
* requested size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsFeatureInBlacklist(const nsCOMPtr<nsIGfxInfo>& gfxInfo, int32_t feature)
|
||||||
|
{
|
||||||
|
int32_t status;
|
||||||
|
if (!NS_SUCCEEDED(gfxInfo->GetFeatureStatus(feature, &status)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return status != nsIGfxInfo::FEATURE_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static already_AddRefed<GLContext>
|
||||||
|
CreateHeadlessNativeGL(bool forceEnabled,
|
||||||
|
const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
||||||
|
WebGLContext* webgl)
|
||||||
|
{
|
||||||
|
if (!forceEnabled &&
|
||||||
|
IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_OPENGL))
|
||||||
|
{
|
||||||
|
webgl->GenerateWarning("Refused to create native OpenGL context"
|
||||||
|
" because of blacklisting.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<GLContext> gl = gl::GLContextProvider::CreateHeadless();
|
||||||
|
if (!gl) {
|
||||||
|
webgl->GenerateWarning("Error during native OpenGL init.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(!gl->IsANGLE());
|
||||||
|
|
||||||
|
return gl.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that we have a separate call for ANGLE and EGL, even though
|
||||||
|
// right now, we get ANGLE implicitly by using EGL on Windows.
|
||||||
|
// Eventually, we want to be able to pick ANGLE-EGL or native EGL.
|
||||||
|
static already_AddRefed<GLContext>
|
||||||
|
CreateHeadlessANGLE(bool forceEnabled,
|
||||||
|
const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
||||||
|
WebGLContext* webgl)
|
||||||
|
{
|
||||||
|
nsRefPtr<GLContext> gl;
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
if (!forceEnabled &&
|
||||||
|
IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_ANGLE))
|
||||||
|
{
|
||||||
|
webgl->GenerateWarning("Refused to create ANGLE OpenGL context"
|
||||||
|
" because of blacklisting.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl = gl::GLContextProviderEGL::CreateHeadless();
|
||||||
|
if (!gl) {
|
||||||
|
webgl->GenerateWarning("Error during ANGLE OpenGL init.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(gl->IsANGLE());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return gl.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
static already_AddRefed<GLContext>
|
||||||
|
CreateHeadlessEGL(bool forceEnabled,
|
||||||
|
const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
||||||
|
WebGLContext* webgl)
|
||||||
|
{
|
||||||
|
nsRefPtr<GLContext> gl;
|
||||||
|
|
||||||
|
#ifdef ANDROID
|
||||||
|
gl = gl::GLContextProviderEGL::CreateHeadless();
|
||||||
|
if (!gl) {
|
||||||
|
webgl->GenerateWarning("Error during EGL OpenGL init.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(!gl->IsANGLE());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return gl.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static already_AddRefed<GLContext>
|
||||||
|
CreateHeadlessGL(bool forceEnabled,
|
||||||
|
const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
||||||
|
WebGLContext* webgl)
|
||||||
|
{
|
||||||
|
bool preferEGL = PR_GetEnv("MOZ_WEBGL_PREFER_EGL");
|
||||||
|
bool disableANGLE = Preferences::GetBool("webgl.disable-angle", false);
|
||||||
|
|
||||||
|
if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL")) {
|
||||||
|
disableANGLE = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<GLContext> gl;
|
||||||
|
|
||||||
|
if (preferEGL)
|
||||||
|
gl = CreateHeadlessEGL(forceEnabled, gfxInfo, webgl);
|
||||||
|
|
||||||
|
if (!gl && !disableANGLE)
|
||||||
|
gl = CreateHeadlessANGLE(forceEnabled, gfxInfo, webgl);
|
||||||
|
|
||||||
|
if (!gl)
|
||||||
|
gl = CreateHeadlessNativeGL(forceEnabled, gfxInfo, webgl);
|
||||||
|
|
||||||
|
return gl.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to create a dummy offscreen with the given caps.
|
||||||
|
static bool
|
||||||
|
CreateOffscreenWithCaps(GLContext* gl, const SurfaceCaps& caps)
|
||||||
|
{
|
||||||
|
gfx::IntSize dummySize(16, 16);
|
||||||
|
return gl->InitOffscreen(dummySize, caps);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
PopulateCapFallbackQueue(const SurfaceCaps& baseCaps,
|
||||||
|
std::queue<SurfaceCaps>* fallbackCaps)
|
||||||
|
{
|
||||||
|
fallbackCaps->push(baseCaps);
|
||||||
|
|
||||||
|
// Dropping antialias drops our quality, but not our correctness.
|
||||||
|
// The user basically doesn't have to handle if this fails, they
|
||||||
|
// just get reduced quality.
|
||||||
|
if (baseCaps.antialias) {
|
||||||
|
SurfaceCaps nextCaps(baseCaps);
|
||||||
|
nextCaps.antialias = false;
|
||||||
|
PopulateCapFallbackQueue(nextCaps, fallbackCaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have to drop one of depth or stencil, we'd prefer to keep
|
||||||
|
// depth. However, the client app will need to handle if this
|
||||||
|
// doesn't work.
|
||||||
|
if (baseCaps.stencil) {
|
||||||
|
SurfaceCaps nextCaps(baseCaps);
|
||||||
|
nextCaps.stencil = false;
|
||||||
|
PopulateCapFallbackQueue(nextCaps, fallbackCaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseCaps.depth) {
|
||||||
|
SurfaceCaps nextCaps(baseCaps);
|
||||||
|
nextCaps.depth = false;
|
||||||
|
PopulateCapFallbackQueue(nextCaps, fallbackCaps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CreateOffscreen(GLContext* gl,
|
||||||
|
const WebGLContextOptions& options,
|
||||||
|
const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
||||||
|
WebGLContext* webgl,
|
||||||
|
layers::ISurfaceAllocator* surfAllocator)
|
||||||
|
{
|
||||||
|
SurfaceCaps baseCaps;
|
||||||
|
|
||||||
|
baseCaps.color = true;
|
||||||
|
baseCaps.alpha = options.alpha;
|
||||||
|
baseCaps.antialias = options.antialias;
|
||||||
|
baseCaps.depth = options.depth;
|
||||||
|
baseCaps.preserve = options.preserveDrawingBuffer;
|
||||||
|
baseCaps.stencil = options.stencil;
|
||||||
|
|
||||||
|
// we should really have this behind a
|
||||||
|
// |gfxPlatform::GetPlatform()->GetScreenDepth() == 16| check, but
|
||||||
|
// for now it's just behind a pref for testing/evaluation.
|
||||||
|
baseCaps.bpp16 = Preferences::GetBool("webgl.prefer-16bpp", false);
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
baseCaps.surfaceAllocator = surfAllocator;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Done with baseCaps construction.
|
||||||
|
|
||||||
|
bool forceAllowAA = Preferences::GetBool("webgl.msaa-force", false);
|
||||||
|
if (!forceAllowAA &&
|
||||||
|
IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_MSAA))
|
||||||
|
{
|
||||||
|
webgl->GenerateWarning("Disallowing antialiased backbuffers due"
|
||||||
|
" to blacklisting.");
|
||||||
|
baseCaps.antialias = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::queue<SurfaceCaps> fallbackCaps;
|
||||||
|
PopulateCapFallbackQueue(baseCaps, &fallbackCaps);
|
||||||
|
|
||||||
|
bool created = false;
|
||||||
|
while (!fallbackCaps.empty()) {
|
||||||
|
SurfaceCaps& caps = fallbackCaps.front();
|
||||||
|
|
||||||
|
created = CreateOffscreenWithCaps(gl, caps);
|
||||||
|
if (created)
|
||||||
|
break;
|
||||||
|
|
||||||
|
fallbackCaps.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WebGLContext::CreateOffscreenGL(bool forceEnabled)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
|
||||||
|
|
||||||
|
layers::ISurfaceAllocator* surfAllocator = nullptr;
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
nsIWidget* docWidget = nsContentUtils::WidgetForDocument(mCanvasElement->OwnerDoc());
|
||||||
|
if (docWidget) {
|
||||||
|
layers::LayerManager* layerManager = docWidget->GetLayerManager();
|
||||||
|
if (layerManager) {
|
||||||
|
// XXX we really want "AsSurfaceAllocator" here for generality
|
||||||
|
layers::ShadowLayerForwarder* forwarder = layerManager->AsShadowForwarder();
|
||||||
|
if (forwarder) {
|
||||||
|
surfAllocator = static_cast<layers::ISurfaceAllocator*>(forwarder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gl = CreateHeadlessGL(forceEnabled, gfxInfo, this);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!gl)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!CreateOffscreen(gl, mOptions, gfxInfo, this, surfAllocator))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!InitAndValidateGL())
|
||||||
|
break;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} while (false);
|
||||||
|
|
||||||
|
gl = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback for resizes:
|
||||||
|
bool
|
||||||
|
WebGLContext::ResizeBackbuffer(uint32_t requestedWidth, uint32_t requestedHeight)
|
||||||
|
{
|
||||||
|
uint32_t width = requestedWidth;
|
||||||
|
uint32_t height = requestedHeight;
|
||||||
|
|
||||||
|
bool resized = false;
|
||||||
|
while (width || height) {
|
||||||
|
width = width ? width : 1;
|
||||||
|
height = height ? height : 1;
|
||||||
|
|
||||||
|
gfx::IntSize curSize(width, height);
|
||||||
|
if (gl->ResizeOffscreen(curSize)) {
|
||||||
|
resized = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
width /= 2;
|
||||||
|
height /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resized)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mWidth = gl->OffscreenSize().width;
|
||||||
|
mHeight = gl->OffscreenSize().height;
|
||||||
|
MOZ_ASSERT((uint32_t)mWidth == width);
|
||||||
|
MOZ_ASSERT((uint32_t)mHeight == height);
|
||||||
|
|
||||||
|
if (width != requestedWidth ||
|
||||||
|
height != requestedHeight)
|
||||||
|
{
|
||||||
|
GenerateWarning("Requested size %dx%d was too large, but resize"
|
||||||
|
" to %dx%d succeeded.",
|
||||||
|
requestedWidth, requestedHeight,
|
||||||
|
width, height);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
WebGLContext::SetDimensions(int32_t width, int32_t height)
|
WebGLContext::SetDimensions(int32_t sWidth, int32_t sHeight)
|
||||||
{
|
{
|
||||||
// Early error return cases
|
// Early error return cases
|
||||||
|
if (!GetCanvas())
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
if (width < 0 || height < 0) {
|
if (sWidth < 0 || sHeight < 0) {
|
||||||
GenerateWarning("Canvas size is too large (seems like a negative value wrapped)");
|
GenerateWarning("Canvas size is too large (seems like a negative value wrapped)");
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetCanvas())
|
uint32_t width = sWidth;
|
||||||
return NS_ERROR_FAILURE;
|
uint32_t height = sHeight;
|
||||||
|
|
||||||
// Early success return cases
|
// Early success return cases
|
||||||
|
|
||||||
GetCanvas()->InvalidateCanvas();
|
GetCanvas()->InvalidateCanvas();
|
||||||
|
|
||||||
if (gl && mWidth == width && mHeight == height)
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
// Zero-sized surfaces can cause problems.
|
// Zero-sized surfaces can cause problems.
|
||||||
if (width == 0) {
|
if (width == 0) {
|
||||||
width = 1;
|
width = 1;
|
||||||
@ -511,20 +808,29 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
|
|||||||
|
|
||||||
// If we already have a gl context, then we just need to resize it
|
// If we already have a gl context, then we just need to resize it
|
||||||
if (gl) {
|
if (gl) {
|
||||||
|
if ((uint32_t)mWidth == width &&
|
||||||
|
(uint32_t)mHeight == height)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsContextLost())
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
// If we've already drawn, we should commit the current buffer.
|
// If we've already drawn, we should commit the current buffer.
|
||||||
PresentScreenBuffer();
|
PresentScreenBuffer();
|
||||||
|
|
||||||
// ResizeOffscreen scraps the current prod buffer before making a new one.
|
// ResizeOffscreen scraps the current prod buffer before making a new one.
|
||||||
gl->ResizeOffscreen(gfx::IntSize(width, height)); // Doesn't matter if it succeeds (soft-fail)
|
if (!ResizeBackbuffer(width, height)) {
|
||||||
// It's unlikely that we'll get a proper-sized context if we recreate if we didn't on resize
|
GenerateWarning("WebGL context failed to resize.");
|
||||||
|
ForceLoseContext();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// everything's good, we're done here
|
// everything's good, we're done here
|
||||||
mWidth = gl->OffscreenSize().width;
|
|
||||||
mHeight = gl->OffscreenSize().height;
|
|
||||||
mResetLayer = true;
|
mResetLayer = true;
|
||||||
|
|
||||||
mBackbufferNeedsClear = true;
|
mBackbufferNeedsClear = true;
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -541,27 +847,6 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
|
|||||||
// and that is what can fail if we already have too many.
|
// and that is what can fail if we already have too many.
|
||||||
LoseOldestWebGLContextIfLimitExceeded();
|
LoseOldestWebGLContextIfLimitExceeded();
|
||||||
|
|
||||||
// Get some prefs for some preferred/overriden things
|
|
||||||
NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
#ifdef XP_WIN
|
|
||||||
bool preferEGL =
|
|
||||||
Preferences::GetBool("webgl.prefer-egl", false);
|
|
||||||
bool preferOpenGL =
|
|
||||||
Preferences::GetBool("webgl.prefer-native-gl", false);
|
|
||||||
#endif
|
|
||||||
bool forceEnabled =
|
|
||||||
Preferences::GetBool("webgl.force-enabled", false);
|
|
||||||
bool disabled =
|
|
||||||
Preferences::GetBool("webgl.disabled", false);
|
|
||||||
bool prefer16bit =
|
|
||||||
Preferences::GetBool("webgl.prefer-16bpp", false);
|
|
||||||
|
|
||||||
ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
|
|
||||||
|
|
||||||
if (disabled)
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
// We're going to create an entirely new context. If our
|
// We're going to create an entirely new context. If our
|
||||||
// generation is not 0 right now (that is, if this isn't the first
|
// generation is not 0 right now (that is, if this isn't the first
|
||||||
// context we're creating), we may have to dispatch a context lost
|
// context we're creating), we may have to dispatch a context lost
|
||||||
@ -570,111 +855,32 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
|
|||||||
// If incrementing the generation would cause overflow,
|
// If incrementing the generation would cause overflow,
|
||||||
// don't allow it. Allowing this would allow us to use
|
// don't allow it. Allowing this would allow us to use
|
||||||
// resource handles created from older context generations.
|
// resource handles created from older context generations.
|
||||||
if (!(mGeneration + 1).isValid())
|
if (!(mGeneration + 1).isValid()) {
|
||||||
|
GenerateWarning("Too many WebGL contexts created this run.");
|
||||||
return NS_ERROR_FAILURE; // exit without changing the value of mGeneration
|
return NS_ERROR_FAILURE; // exit without changing the value of mGeneration
|
||||||
|
|
||||||
SurfaceCaps caps;
|
|
||||||
|
|
||||||
caps.color = true;
|
|
||||||
caps.alpha = mOptions.alpha;
|
|
||||||
caps.depth = mOptions.depth;
|
|
||||||
caps.stencil = mOptions.stencil;
|
|
||||||
|
|
||||||
// we should really have this behind a
|
|
||||||
// |gfxPlatform::GetPlatform()->GetScreenDepth() == 16| check, but
|
|
||||||
// for now it's just behind a pref for testing/evaluation.
|
|
||||||
caps.bpp16 = prefer16bit;
|
|
||||||
|
|
||||||
caps.preserve = mOptions.preserveDrawingBuffer;
|
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
|
||||||
nsIWidget *docWidget = nsContentUtils::WidgetForDocument(mCanvasElement->OwnerDoc());
|
|
||||||
if (docWidget) {
|
|
||||||
layers::LayerManager *layerManager = docWidget->GetLayerManager();
|
|
||||||
if (layerManager) {
|
|
||||||
// XXX we really want "AsSurfaceAllocator" here for generality
|
|
||||||
layers::ShadowLayerForwarder *forwarder = layerManager->AsShadowForwarder();
|
|
||||||
if (forwarder) {
|
|
||||||
caps.surfaceAllocator = static_cast<layers::ISurfaceAllocator*>(forwarder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool forceMSAA =
|
|
||||||
Preferences::GetBool("webgl.msaa-force", false);
|
|
||||||
|
|
||||||
int32_t status;
|
|
||||||
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
|
|
||||||
if (mOptions.antialias &&
|
|
||||||
gfxInfo &&
|
|
||||||
NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBGL_MSAA, &status))) {
|
|
||||||
if (status == nsIGfxInfo::FEATURE_STATUS_OK || forceMSAA) {
|
|
||||||
caps.antialias = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XP_WIN
|
// Get some prefs for some preferred/overriden things
|
||||||
if (PR_GetEnv("MOZ_WEBGL_PREFER_EGL")) {
|
NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
|
||||||
preferEGL = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Ask GfxInfo about what we should use
|
bool disabled = Preferences::GetBool("webgl.disabled", false);
|
||||||
bool useOpenGL = true;
|
if (disabled) {
|
||||||
|
GenerateWarning("WebGL creation is disabled, and so disallowed here.");
|
||||||
#ifdef XP_WIN
|
return NS_ERROR_FAILURE;
|
||||||
bool useANGLE = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (gfxInfo && !forceEnabled) {
|
|
||||||
if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBGL_OPENGL, &status))) {
|
|
||||||
if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
|
|
||||||
useOpenGL = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef XP_WIN
|
|
||||||
if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBGL_ANGLE, &status))) {
|
|
||||||
if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
|
|
||||||
useANGLE = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XP_WIN
|
// Alright, now let's start trying.
|
||||||
// allow forcing GL and not EGL/ANGLE
|
bool forceEnabled = Preferences::GetBool("webgl.force-enabled", false);
|
||||||
if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL")) {
|
ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
|
||||||
preferEGL = false;
|
|
||||||
useANGLE = false;
|
if (!CreateOffscreenGL(forceEnabled)) {
|
||||||
useOpenGL = true;
|
GenerateWarning("WebGL creation failed.");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
#endif
|
MOZ_ASSERT(gl);
|
||||||
|
|
||||||
gfxIntSize size(width, height);
|
if (!ResizeBackbuffer(width, height)) {
|
||||||
|
GenerateWarning("Initializing WebGL backbuffer failed.");
|
||||||
#ifdef XP_WIN
|
|
||||||
// if we want EGL, try it now
|
|
||||||
if (!gl && (preferEGL || useANGLE) && !preferOpenGL) {
|
|
||||||
gl = gl::GLContextProviderEGL::CreateOffscreen(size, caps);
|
|
||||||
if (!gl || !InitAndValidateGL()) {
|
|
||||||
GenerateWarning("Error during ANGLE OpenGL ES initialization");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// try the default provider, whatever that is
|
|
||||||
if (!gl && useOpenGL) {
|
|
||||||
gl = gl::GLContextProvider::CreateOffscreen(size, caps);
|
|
||||||
if (gl && !InitAndValidateGL()) {
|
|
||||||
GenerateWarning("Error during OpenGL initialization");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gl) {
|
|
||||||
GenerateWarning("Can't get a usable WebGL context");
|
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -684,23 +890,18 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mWidth = width;
|
|
||||||
mHeight = height;
|
|
||||||
mViewportWidth = width;
|
|
||||||
mViewportHeight = height;
|
|
||||||
mResetLayer = true;
|
mResetLayer = true;
|
||||||
mOptionsFrozen = true;
|
mOptionsFrozen = true;
|
||||||
|
|
||||||
// increment the generation number
|
// increment the generation number
|
||||||
++mGeneration;
|
++mGeneration;
|
||||||
#if 0
|
|
||||||
if (mGeneration > 0) {
|
|
||||||
// XXX dispatch context lost event
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
|
||||||
|
gl->fViewport(0, 0, mWidth, mHeight);
|
||||||
|
mViewportWidth = mWidth;
|
||||||
|
mViewportHeight = mHeight;
|
||||||
|
|
||||||
// Make sure that we clear this out, otherwise
|
// Make sure that we clear this out, otherwise
|
||||||
// we'll end up displaying random memory
|
// we'll end up displaying random memory
|
||||||
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
|
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
|
||||||
@ -715,12 +916,12 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
|
|||||||
|
|
||||||
mShouldPresent = true;
|
mShouldPresent = true;
|
||||||
|
|
||||||
MOZ_ASSERT(gl->Caps().color == caps.color);
|
MOZ_ASSERT(gl->Caps().color);
|
||||||
MOZ_ASSERT(gl->Caps().alpha == caps.alpha);
|
MOZ_ASSERT(gl->Caps().alpha == mOptions.alpha);
|
||||||
MOZ_ASSERT(gl->Caps().depth == caps.depth || !gl->Caps().depth);
|
MOZ_ASSERT(gl->Caps().depth == mOptions.depth || !gl->Caps().depth);
|
||||||
MOZ_ASSERT(gl->Caps().stencil == caps.stencil || !gl->Caps().stencil);
|
MOZ_ASSERT(gl->Caps().stencil == mOptions.stencil || !gl->Caps().stencil);
|
||||||
MOZ_ASSERT(gl->Caps().antialias == caps.antialias || !gl->Caps().antialias);
|
MOZ_ASSERT(gl->Caps().antialias == mOptions.antialias || !gl->Caps().antialias);
|
||||||
MOZ_ASSERT(gl->Caps().preserve == caps.preserve);
|
MOZ_ASSERT(gl->Caps().preserve == mOptions.preserveDrawingBuffer);
|
||||||
|
|
||||||
AssertCachedBindings();
|
AssertCachedBindings();
|
||||||
AssertCachedState();
|
AssertCachedState();
|
||||||
@ -1211,7 +1412,7 @@ WebGLContext::PresentScreenBuffer()
|
|||||||
gl->MakeCurrent();
|
gl->MakeCurrent();
|
||||||
MOZ_ASSERT(!mBackbufferNeedsClear);
|
MOZ_ASSERT(!mBackbufferNeedsClear);
|
||||||
if (!gl->PublishFrame()) {
|
if (!gl->PublishFrame()) {
|
||||||
this->ForceLoseContext();
|
ForceLoseContext();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1036,7 +1036,9 @@ protected:
|
|||||||
// Validation functions (implemented in WebGLContextValidate.cpp)
|
// Validation functions (implemented in WebGLContextValidate.cpp)
|
||||||
GLenum BaseTexFormat(GLenum internalFormat) const;
|
GLenum BaseTexFormat(GLenum internalFormat) const;
|
||||||
|
|
||||||
|
bool CreateOffscreenGL(bool forceEnabled);
|
||||||
bool InitAndValidateGL();
|
bool InitAndValidateGL();
|
||||||
|
bool ResizeBackbuffer(uint32_t width, uint32_t height);
|
||||||
bool ValidateBlendEquationEnum(GLenum cap, const char *info);
|
bool ValidateBlendEquationEnum(GLenum cap, const char *info);
|
||||||
bool ValidateBlendFuncDstEnum(GLenum mode, const char *info);
|
bool ValidateBlendFuncDstEnum(GLenum mode, const char *info);
|
||||||
bool ValidateBlendFuncSrcEnum(GLenum mode, const char *info);
|
bool ValidateBlendFuncSrcEnum(GLenum mode, const char *info);
|
||||||
|
@ -175,10 +175,10 @@ skip-if(winWidget) pref(webgl.prefer-16bpp,true)
|
|||||||
skip-if(winWidget) pref(webgl.prefer-16bpp,true) pref(webgl.force-layers-readback,true) random-if(Android&&AndroidVersion<15) == webgl-color-test.html?16bpp&readback wrapper.html?colors.png
|
skip-if(winWidget) pref(webgl.prefer-16bpp,true) pref(webgl.force-layers-readback,true) random-if(Android&&AndroidVersion<15) == webgl-color-test.html?16bpp&readback wrapper.html?colors.png
|
||||||
|
|
||||||
# Force native GL (Windows):
|
# Force native GL (Windows):
|
||||||
skip-if(!winWidget) pref(webgl.prefer-native-gl,true) == webgl-clear-test.html?native-gl wrapper.html?green.png
|
skip-if(!winWidget) pref(webgl.disable-angle,true) == webgl-clear-test.html?native-gl wrapper.html?green.png
|
||||||
skip-if(!winWidget) pref(webgl.prefer-native-gl,true) == webgl-orientation-test.html?native-gl wrapper.html?white-top-left.png
|
skip-if(!winWidget) pref(webgl.disable-angle,true) == webgl-orientation-test.html?native-gl wrapper.html?white-top-left.png
|
||||||
skip-if(!winWidget) pref(webgl.prefer-native-gl,true) == webgl-color-test.html?native-gl wrapper.html?colors.png
|
skip-if(!winWidget) pref(webgl.disable-angle,true) == webgl-color-test.html?native-gl wrapper.html?colors.png
|
||||||
skip-if(!winWidget) pref(webgl.prefer-native-gl,true) pref(webgl.prefer-16bpp,true) == webgl-color-test.html?native-gl&16bpp wrapper.html?colors.png
|
skip-if(!winWidget) pref(webgl.disable-angle,true) pref(webgl.prefer-16bpp,true) == webgl-color-test.html?native-gl&16bpp wrapper.html?colors.png
|
||||||
|
|
||||||
|
|
||||||
# Non-WebGL Reftests!
|
# Non-WebGL Reftests!
|
||||||
|
@ -1112,6 +1112,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
|||||||
raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
|
raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
|
||||||
raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
|
raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
|
||||||
raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
|
raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
|
||||||
|
raw_fGetIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
|
||||||
|
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
if (mWorkAroundDriverBugs) {
|
if (mWorkAroundDriverBugs) {
|
||||||
@ -1127,8 +1128,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
|||||||
// See bug 879656. 8192 fails, 8191 works.
|
// See bug 879656. 8192 fails, 8191 works.
|
||||||
mMaxTextureSize = std::min(mMaxTextureSize, 8191);
|
mMaxTextureSize = std::min(mMaxTextureSize, 8191);
|
||||||
mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 8191);
|
mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 8191);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// See bug 877949.
|
// See bug 877949.
|
||||||
mMaxTextureSize = std::min(mMaxTextureSize, 4096);
|
mMaxTextureSize = std::min(mMaxTextureSize, 4096);
|
||||||
mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096);
|
mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096);
|
||||||
|
@ -2985,6 +2985,7 @@ protected:
|
|||||||
GLint mMaxCubeMapTextureSize;
|
GLint mMaxCubeMapTextureSize;
|
||||||
GLint mMaxTextureImageSize;
|
GLint mMaxTextureImageSize;
|
||||||
GLint mMaxRenderbufferSize;
|
GLint mMaxRenderbufferSize;
|
||||||
|
GLint mMaxViewportDims[2];
|
||||||
GLsizei mMaxSamples;
|
GLsizei mMaxSamples;
|
||||||
bool mNeedsTextureSizeChecks;
|
bool mNeedsTextureSizeChecks;
|
||||||
bool mWorkAroundDriverBugs;
|
bool mWorkAroundDriverBugs;
|
||||||
|
@ -247,25 +247,33 @@ CreateOffscreenFBOContext(bool aShare = true)
|
|||||||
return glContext.forget();
|
return glContext.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<GLContext>
|
||||||
|
GLContextProviderCGL::CreateHeadless()
|
||||||
|
{
|
||||||
|
nsRefPtr<GLContextCGL> glContext = CreateOffscreenFBOContext();
|
||||||
|
if (!glContext)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (!glContext->Init())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return glContext.forget();
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<GLContext>
|
already_AddRefed<GLContext>
|
||||||
GLContextProviderCGL::CreateOffscreen(const gfxIntSize& size,
|
GLContextProviderCGL::CreateOffscreen(const gfxIntSize& size,
|
||||||
const SurfaceCaps& caps)
|
const SurfaceCaps& caps)
|
||||||
{
|
{
|
||||||
nsRefPtr<GLContextCGL> glContext = CreateOffscreenFBOContext();
|
nsRefPtr<GLContext> glContext = CreateHeadless();
|
||||||
if (glContext &&
|
if (!glContext->InitOffscreen(ToIntSize(size), caps))
|
||||||
glContext->Init() &&
|
return nullptr;
|
||||||
glContext->InitOffscreen(ToIntSize(size), caps))
|
|
||||||
{
|
|
||||||
return glContext.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
// everything failed
|
return glContext.forget();
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsRefPtr<GLContext> gGlobalContext;
|
static nsRefPtr<GLContext> gGlobalContext;
|
||||||
|
|
||||||
GLContext *
|
GLContext*
|
||||||
GLContextProviderCGL::GetGlobalContext()
|
GLContextProviderCGL::GetGlobalContext()
|
||||||
{
|
{
|
||||||
if (!sCGLLibrary.EnsureInitialized()) {
|
if (!sCGLLibrary.EnsureInitialized()) {
|
||||||
|
@ -878,20 +878,29 @@ GLContextEGL::CreateEGLPixmapOffscreenContext(const gfxIntSize& size)
|
|||||||
return glContext.forget();
|
return glContext.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Under EGL, on Android, pbuffers are supported fine, though
|
|
||||||
// often without the ability to texture from them directly.
|
|
||||||
already_AddRefed<GLContext>
|
already_AddRefed<GLContext>
|
||||||
GLContextProviderEGL::CreateOffscreen(const gfxIntSize& size,
|
GLContextProviderEGL::CreateHeadless()
|
||||||
const SurfaceCaps& caps)
|
|
||||||
{
|
{
|
||||||
if (!sEGLLibrary.EnsureInitialized()) {
|
if (!sEGLLibrary.EnsureInitialized()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxIntSize dummySize = gfxIntSize(16, 16);
|
gfxIntSize dummySize = gfxIntSize(16, 16);
|
||||||
nsRefPtr<GLContextEGL> glContext;
|
nsRefPtr<GLContext> glContext;
|
||||||
glContext = GLContextEGL::CreateEGLPBufferOffscreenContext(dummySize);
|
glContext = GLContextEGL::CreateEGLPBufferOffscreenContext(dummySize);
|
||||||
|
if (!glContext)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return glContext.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Under EGL, on Android, pbuffers are supported fine, though
|
||||||
|
// often without the ability to texture from them directly.
|
||||||
|
already_AddRefed<GLContext>
|
||||||
|
GLContextProviderEGL::CreateOffscreen(const gfxIntSize& size,
|
||||||
|
const SurfaceCaps& caps)
|
||||||
|
{
|
||||||
|
nsRefPtr<GLContext> glContext = CreateHeadless();
|
||||||
if (!glContext)
|
if (!glContext)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -904,7 +913,7 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& size,
|
|||||||
// Don't want a global context on Android as 1) share groups across 2 threads fail on many Tegra drivers (bug 759225)
|
// Don't want a global context on Android as 1) share groups across 2 threads fail on many Tegra drivers (bug 759225)
|
||||||
// and 2) some mobile devices have a very strict limit on global number of GL contexts (bug 754257)
|
// and 2) some mobile devices have a very strict limit on global number of GL contexts (bug 754257)
|
||||||
// and 3) each EGL context eats 750k on B2G (bug 813783)
|
// and 3) each EGL context eats 750k on B2G (bug 813783)
|
||||||
GLContext *
|
GLContext*
|
||||||
GLContextProviderEGL::GetGlobalContext()
|
GLContextProviderEGL::GetGlobalContext()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1212,14 +1212,22 @@ DONE_CREATING_PIXMAP:
|
|||||||
return glContext.forget();
|
return glContext.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<GLContext>
|
||||||
|
GLContextProviderGLX::CreateHeadless()
|
||||||
|
{
|
||||||
|
gfxIntSize dummySize = gfxIntSize(16, 16);
|
||||||
|
nsRefPtr<GLContext> glContext = CreateOffscreenPixmapContext(dummySize);
|
||||||
|
if (!glContext)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return glContext.forget();
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<GLContext>
|
already_AddRefed<GLContext>
|
||||||
GLContextProviderGLX::CreateOffscreen(const gfxIntSize& size,
|
GLContextProviderGLX::CreateOffscreen(const gfxIntSize& size,
|
||||||
const SurfaceCaps& caps)
|
const SurfaceCaps& caps)
|
||||||
{
|
{
|
||||||
gfxIntSize dummySize = gfxIntSize(16, 16);
|
nsRefPtr<GLContext> glContext = CreateHeadless();
|
||||||
nsRefPtr<GLContextGLX> glContext =
|
|
||||||
CreateOffscreenPixmapContext(dummySize);
|
|
||||||
|
|
||||||
if (!glContext)
|
if (!glContext)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -60,6 +60,10 @@ public:
|
|||||||
CreateOffscreen(const gfxIntSize& size,
|
CreateOffscreen(const gfxIntSize& size,
|
||||||
const SurfaceCaps& caps);
|
const SurfaceCaps& caps);
|
||||||
|
|
||||||
|
// Just create a context. We'll add offscreen stuff ourselves.
|
||||||
|
static already_AddRefed<GLContext>
|
||||||
|
CreateHeadless();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create wrapping Gecko GLContext for external gl context.
|
* Create wrapping Gecko GLContext for external gl context.
|
||||||
*
|
*
|
||||||
|
@ -22,8 +22,13 @@ GLContextProviderNull::CreateWrappingExisting(void*, void*)
|
|||||||
|
|
||||||
already_AddRefed<GLContext>
|
already_AddRefed<GLContext>
|
||||||
GLContextProviderNull::CreateOffscreen(const gfxIntSize&,
|
GLContextProviderNull::CreateOffscreen(const gfxIntSize&,
|
||||||
const SurfaceCaps&,
|
const SurfaceCaps&)
|
||||||
ContextFlags)
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<GLContext>
|
||||||
|
GLContextProviderNull::CreateHeadless()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -607,8 +607,7 @@ CreateWindowOffscreenContext()
|
|||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<GLContext>
|
already_AddRefed<GLContext>
|
||||||
GLContextProviderWGL::CreateOffscreen(const gfxIntSize& size,
|
GLContextProviderWGL::CreateHeadless()
|
||||||
const SurfaceCaps& caps)
|
|
||||||
{
|
{
|
||||||
if (!sWGLLib.EnsureInitialized()) {
|
if (!sWGLLib.EnsureInitialized()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -636,6 +635,18 @@ GLContextProviderWGL::CreateOffscreen(const gfxIntSize& size,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsRefPtr<GLContext> retGL = glContext;
|
||||||
|
return retGL.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<GLContext>
|
||||||
|
GLContextProviderWGL::CreateOffscreen(const gfxIntSize& size,
|
||||||
|
const SurfaceCaps& caps)
|
||||||
|
{
|
||||||
|
nsRefPtr<GLContext> glContext = CreateHeadless();
|
||||||
|
if (!glContext)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
if (!glContext->InitOffscreen(ToIntSize(size), caps))
|
if (!glContext->InitOffscreen(ToIntSize(size), caps))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -12,42 +12,42 @@ namespace gl {
|
|||||||
|
|
||||||
SurfaceCaps::SurfaceCaps()
|
SurfaceCaps::SurfaceCaps()
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceCaps::SurfaceCaps(const SurfaceCaps& other)
|
SurfaceCaps::SurfaceCaps(const SurfaceCaps& other)
|
||||||
{
|
{
|
||||||
*this = other;
|
*this = other;
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceCaps&
|
SurfaceCaps&
|
||||||
SurfaceCaps::operator=(const SurfaceCaps& other)
|
SurfaceCaps::operator=(const SurfaceCaps& other)
|
||||||
{
|
{
|
||||||
any = other.any;
|
any = other.any;
|
||||||
color = other.color;
|
color = other.color;
|
||||||
alpha = other.alpha;
|
alpha = other.alpha;
|
||||||
bpp16 = other.bpp16;
|
bpp16 = other.bpp16;
|
||||||
depth = other.depth;
|
depth = other.depth;
|
||||||
stencil = other.stencil;
|
stencil = other.stencil;
|
||||||
antialias = other.antialias;
|
antialias = other.antialias;
|
||||||
preserve = other.preserve;
|
preserve = other.preserve;
|
||||||
surfaceAllocator = other.surfaceAllocator;
|
surfaceAllocator = other.surfaceAllocator;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SurfaceCaps::Clear()
|
SurfaceCaps::Clear()
|
||||||
{
|
{
|
||||||
any = false;
|
any = false;
|
||||||
color = false;
|
color = false;
|
||||||
alpha = false;
|
alpha = false;
|
||||||
bpp16 = false;
|
bpp16 = false;
|
||||||
depth = false;
|
depth = false;
|
||||||
stencil = false;
|
stencil = false;
|
||||||
antialias = false;
|
antialias = false;
|
||||||
preserve = false;
|
preserve = false;
|
||||||
surfaceAllocator = nullptr;
|
surfaceAllocator = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceCaps::~SurfaceCaps()
|
SurfaceCaps::~SurfaceCaps()
|
||||||
|
@ -3712,7 +3712,7 @@ pref("gl.msaa-level", 2);
|
|||||||
pref("webgl.force-enabled", false);
|
pref("webgl.force-enabled", false);
|
||||||
pref("webgl.disabled", false);
|
pref("webgl.disabled", false);
|
||||||
pref("webgl.shader_validator", true);
|
pref("webgl.shader_validator", true);
|
||||||
pref("webgl.prefer-native-gl", false);
|
pref("webgl.disable-angle", false);
|
||||||
pref("webgl.min_capability_mode", false);
|
pref("webgl.min_capability_mode", false);
|
||||||
pref("webgl.disable-extensions", false);
|
pref("webgl.disable-extensions", false);
|
||||||
pref("webgl.msaa-force", false);
|
pref("webgl.msaa-force", false);
|
||||||
|
Loading…
Reference in New Issue
Block a user