Bug 1427668 - Move the webgl backbuffer into webgl. - r=daoshengmu

MozReview-Commit-ID: 2WpG7mfMRQ8
This commit is contained in:
Jeff Gilbert 2017-12-18 18:30:56 -08:00
Родитель 3f0aacfb10
Коммит df8e8db803
20 изменённых файлов: 526 добавлений и 577 удалений

Просмотреть файл

@ -225,14 +225,7 @@ OffscreenCanvas::TransferToImageBitmap(ErrorResult& aRv)
return nullptr;
}
// Clear the content.
if ((mCurrentContextType == CanvasContextType::WebGL1 ||
mCurrentContextType == CanvasContextType::WebGL2))
{
WebGLContext* webGL = static_cast<WebGLContext*>(mCurrentContext.get());
webGL->ClearScreen();
}
// TODO: Clear the content?
return result.forget();
}

Просмотреть файл

@ -40,29 +40,18 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
////
const auto& readFB = mBoundReadFramebuffer;
if (readFB &&
!readFB->ValidateAndInitAttachments("blitFramebuffer's READ_FRAMEBUFFER"))
if (!ValidateAndInitFB("blitFramebuffer: READ_FRAMEBUFFER", mBoundReadFramebuffer) ||
!ValidateAndInitFB("blitFramebuffer: DRAW_FRAMEBUFFER", mBoundDrawFramebuffer))
{
return;
}
const auto& drawFB = mBoundDrawFramebuffer;
if (drawFB &&
!drawFB->ValidateAndInitAttachments("blitFramebuffer's DRAW_FRAMEBUFFER"))
{
return;
}
////
if (!mBoundReadFramebuffer) {
ClearBackbufferIfNeeded();
}
DoBindFB(mBoundReadFramebuffer, LOCAL_GL_READ_FRAMEBUFFER);
DoBindFB(mBoundDrawFramebuffer, LOCAL_GL_DRAW_FRAMEBUFFER);
WebGLFramebuffer::BlitFramebuffer(this,
readFB, srcX0, srcY0, srcX1, srcY1,
drawFB, dstX0, dstY0, dstX1, dstY1,
srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1,
mask, filter);
}
@ -170,23 +159,25 @@ WebGLContext::ValidateInvalidateFramebuffer(const char* funcName, GLenum target,
return false;
const WebGLFramebuffer* fb;
bool isDefaultFB;
bool isDefaultFB = false;
switch (target) {
case LOCAL_GL_FRAMEBUFFER:
case LOCAL_GL_DRAW_FRAMEBUFFER:
fb = mBoundDrawFramebuffer;
isDefaultFB = gl->Screen()->IsDrawFramebufferDefault();
break;
case LOCAL_GL_READ_FRAMEBUFFER:
fb = mBoundReadFramebuffer;
isDefaultFB = gl->Screen()->IsReadFramebufferDefault();
break;
default:
MOZ_CRASH("GFX: Bad target.");
}
if (!ValidateAndInitFB(funcName, fb))
return false;
DoBindFB(fb, target);
*out_glNumAttachments = attachments.Length();
*out_glAttachments = attachments.Elements();
@ -230,13 +221,9 @@ WebGLContext::ValidateInvalidateFramebuffer(const char* funcName, GLenum target,
////
if (!fb) {
ClearBackbufferIfNeeded();
// Don't do more validation after these.
Invalidate();
mShouldPresent = true;
mDefaultFB_IsInvalid = true;
mResolvedDefaultFB = nullptr;
}
return true;
}
@ -331,7 +318,7 @@ WebGL2Context::ReadBuffer(GLenum mode)
return;
}
gl->Screen()->SetReadBuffer(mode);
mDefaultFB_ReadBuffer = mode;
}
} // namespace mozilla

Просмотреть файл

@ -62,11 +62,11 @@ WebGL2Context::ValidateClearBuffer(const char* funcName, GLenum buffer, GLint dr
////
if (!BindCurFBForDraw(funcName))
return false;
const auto& fb = mBoundDrawFramebuffer;
if (fb) {
if (!fb->ValidateAndInitAttachments(funcName))
return false;
if (!fb->ValidateClearBufferType(funcName, buffer, drawBuffer, funcType))
return false;
} else if (buffer == LOCAL_GL_COLOR) {
@ -110,6 +110,13 @@ WebGL2Context::ClearBufferfv(GLenum buffer, GLint drawBuffer, const Float32Arr&
return;
}
if (!mBoundDrawFramebuffer &&
buffer == LOCAL_GL_DEPTH &&
mNeedsFakeNoDepth)
{
return;
}
ScopedDrawCallWrapper wrapper(*this);
const auto ptr = src.elemBytes + srcElemOffset;
gl->fClearBufferfv(buffer, drawBuffer, ptr);
@ -136,6 +143,13 @@ WebGL2Context::ClearBufferiv(GLenum buffer, GLint drawBuffer, const Int32Arr& sr
return;
}
if (!mBoundDrawFramebuffer &&
buffer == LOCAL_GL_STENCIL &&
mNeedsFakeNoStencil)
{
return;
}
ScopedDrawCallWrapper wrapper(*this);
const auto ptr = src.elemBytes + srcElemOffset;
gl->fClearBufferiv(buffer, drawBuffer, ptr);
@ -179,8 +193,18 @@ WebGL2Context::ClearBufferfi(GLenum buffer, GLint drawBuffer, GLfloat depth,
if (!ValidateClearBuffer(funcName, buffer, drawBuffer, 2, 0, 0))
return;
auto driverDepth = depth;
auto driverStencil = stencil;
if (!mBoundDrawFramebuffer) {
if (mNeedsFakeNoDepth) {
driverDepth = 1.0f;
} else if (mNeedsFakeNoStencil) {
driverStencil = 0;
}
}
ScopedDrawCallWrapper wrapper(*this);
gl->fClearBufferfi(buffer, drawBuffer, depth, stencil);
gl->fClearBufferfi(buffer, drawBuffer, driverDepth, driverStencil);
}
} // namespace mozilla

Просмотреть файл

@ -45,7 +45,7 @@ WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
/* GLenum */
case LOCAL_GL_READ_BUFFER: {
if (!mBoundReadFramebuffer)
return JS::Int32Value(gl->Screen()->GetReadBufferMode());
return JS::Int32Value(mDefaultFB_ReadBuffer);
if (!mBoundReadFramebuffer->ColorReadBuffer())
return JS::Int32Value(LOCAL_GL_NONE);

Просмотреть файл

@ -14,6 +14,7 @@
#include "gfxPattern.h"
#include "gfxPrefs.h"
#include "gfxUtils.h"
#include "gfx/gl/MozFramebuffer.h"
#include "GLBlitHelper.h"
#include "GLContext.h"
#include "GLContextProvider.h"
@ -119,8 +120,8 @@ WebGLContext::WebGLContext()
, mNeedsFakeNoAlpha(false)
, mNeedsFakeNoDepth(false)
, mNeedsFakeNoStencil(false)
, mNeedsEmulatedLoneDepthStencil(false)
, mAllowFBInvalidation(gfxPrefs::WebGLFBInvalidation())
, mMsaaSamples(gfxPrefs::WebGLMsaaSamples())
{
mGeneration = 0;
mInvalidated = false;
@ -134,17 +135,6 @@ WebGLContext::WebGLContext()
mWebGLError = 0;
mUnderlyingGLError = 0;
mActiveTexture = 0;
mStencilRefFront = 0;
mStencilRefBack = 0;
mStencilValueMaskFront = 0;
mStencilValueMaskBack = 0;
mStencilWriteMaskFront = 0;
mStencilWriteMaskBack = 0;
mDepthWriteMask = 0;
mStencilClearValue = 0;
mDepthClearValue = 0;
mContextLostErrorSet = false;
mViewportX = 0;
@ -212,6 +202,9 @@ WebGLContext::DestroyResourcesAndContext()
if (!gl)
return;
mDefaultFB = nullptr;
mResolvedDefaultFB = nullptr;
mBound2DTextures.Clear();
mBoundCubeMapTextures.Clear();
mBound3DTextures.Clear();
@ -295,6 +288,7 @@ WebGLContext::DestroyResourcesAndContext()
}
MOZ_ASSERT(gl);
gl->MarkDestroyed();
mGL_OnlyClearInDestroyResourcesAndContext = nullptr;
MOZ_ASSERT(!gl);
}
@ -398,18 +392,6 @@ WebGLContext::SetContextOptions(JSContext* cx, JS::Handle<JS::Value> options,
return NS_OK;
}
int32_t
WebGLContext::GetWidth() const
{
return mWidth;
}
int32_t
WebGLContext::GetHeight() const
{
return mHeight;
}
/* 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
@ -486,30 +468,6 @@ PopulateCapFallbackQueue(const gl::SurfaceCaps& baseCaps,
std::queue<gl::SurfaceCaps>* out_fallbackCaps)
{
out_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) {
gl::SurfaceCaps nextCaps(baseCaps);
nextCaps.antialias = false;
PopulateCapFallbackQueue(nextCaps, out_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) {
gl::SurfaceCaps nextCaps(baseCaps);
nextCaps.stencil = false;
PopulateCapFallbackQueue(nextCaps, out_fallbackCaps);
}
if (baseCaps.depth) {
gl::SurfaceCaps nextCaps(baseCaps);
nextCaps.depth = false;
PopulateCapFallbackQueue(nextCaps, out_fallbackCaps);
}
}
static gl::SurfaceCaps
@ -518,22 +476,16 @@ BaseCaps(const WebGLContextOptions& options, WebGLContext* webgl)
gl::SurfaceCaps baseCaps;
baseCaps.color = true;
baseCaps.alpha = options.alpha;
baseCaps.antialias = options.antialias;
baseCaps.depth = options.depth;
baseCaps.alpha = true;
baseCaps.antialias = false;
baseCaps.depth = false;
baseCaps.stencil = false;
baseCaps.premultAlpha = options.premultipliedAlpha;
baseCaps.preserve = options.preserveDrawingBuffer;
baseCaps.stencil = options.stencil;
if (!baseCaps.alpha)
if (!baseCaps.alpha) {
baseCaps.premultAlpha = true;
// 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 = gfxPrefs::WebGLPrefer16bpp();
// Done with baseCaps construction.
}
if (!gfxPrefs::WebGLForceMSAA()) {
const nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
@ -772,8 +724,8 @@ WebGLContext::CreateAndInitGL(bool forceEnabled,
//////
if (tryANGLE) {
// Force enable alpha channel to make sure ANGLE use correct framebuffer formart
gl::SurfaceCaps& angleCaps = const_cast<gl::SurfaceCaps&>(baseCaps);
// Force enable alpha channel to make sure ANGLE use correct framebuffer format
auto angleCaps = baseCaps;
angleCaps.alpha = true;
return CreateAndInitGLWith(CreateGLWithANGLE, angleCaps, flags, out_failReasons);
}
@ -786,43 +738,54 @@ WebGLContext::CreateAndInitGL(bool forceEnabled,
}
// Fallback for resizes:
bool
WebGLContext::ResizeBackbuffer(uint32_t requestedWidth,
uint32_t requestedHeight)
WebGLContext::EnsureDefaultFB() const
{
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 (mDefaultFB) {
MOZ_ASSERT(mDefaultFB->mSize == mRequestedSize);
return true;
}
if (!resized)
const bool depthStencil = mOptions.depth || mOptions.stencil;
auto attemptSize = mRequestedSize;
while (attemptSize.width || attemptSize.height) {
attemptSize.width = std::max(attemptSize.width, 1);
attemptSize.height = std::max(attemptSize.height, 1);
[&]() {
if (mOptions.antialias) {
MOZ_ASSERT(!mDefaultFB);
mDefaultFB = MozFramebuffer::Create(gl, attemptSize, mMsaaSamples,
depthStencil);
if (mDefaultFB)
return;
if (mOptionsFrozen)
return;
}
MOZ_ASSERT(!mDefaultFB);
mDefaultFB = MozFramebuffer::Create(gl, attemptSize, 0, depthStencil);
}();
if (mDefaultFB)
break;
attemptSize.width /= 2;
attemptSize.height /= 2;
}
if (!mDefaultFB)
return false;
mWidth = gl->OffscreenSize().width;
mHeight = gl->OffscreenSize().height;
MOZ_ASSERT((uint32_t)mWidth == width);
MOZ_ASSERT((uint32_t)mHeight == height);
mDefaultFB_IsInvalid = true;
if (width != requestedWidth ||
height != requestedHeight)
{
if (mDefaultFB->mSize != mRequestedSize) {
GenerateWarning("Requested size %dx%d was too large, but resize"
" to %dx%d succeeded.",
requestedWidth, requestedHeight,
width, height);
mRequestedSize.width, mRequestedSize.height,
mDefaultFB->mSize.width, mDefaultFB->mSize.height);
}
return true;
}
@ -887,8 +850,8 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
// If we already have a gl context, then we just need to resize it
if (gl) {
if ((uint32_t)mWidth == width &&
(uint32_t)mHeight == height)
if (uint32_t(mRequestedSize.width) == width &&
uint32_t(mRequestedSize.height) == height)
{
return NS_OK;
}
@ -904,19 +867,11 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
return NS_OK;
}
// ResizeOffscreen scraps the current prod buffer before making a new one.
if (!ResizeBackbuffer(width, height)) {
GenerateWarning("WebGL context failed to resize.");
ForceLoseContext();
return NS_OK;
}
// Kill our current default fb(s), for later lazy allocation.
mRequestedSize = {width, height};
mDefaultFB = nullptr;
// everything's good, we're done here
mResetLayer = true;
mBackbufferNeedsClear = true;
gl->ResetSyncCallCount("Existing WebGLContext resized.");
return NS_OK;
}
@ -1043,7 +998,9 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
#endif
}
if (!ResizeBackbuffer(width, height)) {
MOZ_ASSERT(!mDefaultFB);
mRequestedSize = {width, height};
if (!EnsureDefaultFB()) {
failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_BACKBUFFER");
const nsLiteralCString text("Initializing WebGL backbuffer failed.");
ThrowEvent_WebGLContextCreationError(text);
@ -1054,50 +1011,40 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
printf_stderr("--- WebGL context created: %p\n", gl.get());
}
mResetLayer = true;
mOptionsFrozen = true;
// Update our internal stuff:
if (gl->WorkAroundDriverBugs()) {
if (!mOptions.alpha && gl->Caps().alpha)
mNeedsFakeNoAlpha = true;
mOptions.antialias = bool(mDefaultFB->mSamples);
if (!mOptions.depth && gl->Caps().depth)
mNeedsFakeNoDepth = true;
if (!mOptions.stencil && gl->Caps().stencil)
mNeedsFakeNoStencil = true;
#ifdef MOZ_WIDGET_COCOA
if (!nsCocoaFeatures::IsAtLeastVersion(10, 12) &&
gl->Vendor() == GLVendor::Intel)
{
mNeedsEmulatedLoneDepthStencil = true;
}
#endif
if (!mOptions.alpha) {
// We always have alpha.
mNeedsFakeNoAlpha = true;
}
// Update mOptions.
if (!gl->Caps().depth)
mOptions.depth = false;
if (mOptions.depth || mOptions.stencil) {
// We always have depth+stencil if we have either.
if (!mOptions.depth) {
mNeedsFakeNoDepth = true;
}
if (!mOptions.stencil) {
mNeedsFakeNoStencil = true;
}
}
if (!gl->Caps().stencil)
mOptions.stencil = false;
mOptions.antialias = gl->Caps().antialias;
mResetLayer = true;
mOptionsFrozen = true;
//////
// Initial setup.
gl->mImplicitMakeCurrent = true;
gl->fViewport(0, 0, mWidth, mHeight);
mViewportX = mViewportY = 0;
mViewportWidth = mWidth;
mViewportHeight = mHeight;
const auto& size = mDefaultFB->mSize;
gl->fScissor(0, 0, mWidth, mHeight);
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
mViewportX = mViewportY = 0;
mViewportWidth = size.width;
mViewportHeight = size.height;
gl->fViewport(mViewportX, mViewportY, mViewportWidth, mViewportHeight);
gl->fScissor(0, 0, size.width, size.height);
//////
// Check everything
@ -1105,25 +1052,6 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
AssertCachedBindings();
AssertCachedGlobalState();
MOZ_ASSERT(gl->Caps().color);
MOZ_ASSERT_IF(!mNeedsFakeNoAlpha, gl->Caps().alpha == mOptions.alpha);
MOZ_ASSERT_IF(mNeedsFakeNoAlpha, !mOptions.alpha && gl->Caps().alpha);
MOZ_ASSERT_IF(!mNeedsFakeNoDepth, gl->Caps().depth == mOptions.depth);
MOZ_ASSERT_IF(mNeedsFakeNoDepth, !mOptions.depth && gl->Caps().depth);
MOZ_ASSERT_IF(!mNeedsFakeNoStencil, gl->Caps().stencil == mOptions.stencil);
MOZ_ASSERT_IF(mNeedsFakeNoStencil, !mOptions.stencil && gl->Caps().stencil);
MOZ_ASSERT(gl->Caps().antialias == mOptions.antialias);
MOZ_ASSERT(gl->Caps().preserve == mOptions.preserveDrawingBuffer);
//////
// Clear immediately, because we need to present the cleared initial buffer
mBackbufferNeedsClear = true;
ClearBackbufferIfNeeded();
mShouldPresent = true;
//////
@ -1136,17 +1064,6 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
return NS_OK;
}
void
WebGLContext::ClearBackbufferIfNeeded()
{
if (!mBackbufferNeedsClear)
return;
ClearScreen();
mBackbufferNeedsClear = false;
}
void
WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
{
@ -1403,8 +1320,8 @@ WebGLContext::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
}
data.mGLContext = gl;
data.mSize = nsIntSize(mWidth, mHeight);
data.mHasAlpha = gl->Caps().alpha;
data.mSize = DrawingBufferSize();
data.mHasAlpha = mOptions.alpha;
data.mIsGLAlphaPremult = IsPremultAlpha() || !data.mHasAlpha;
aRenderer->Initialize(data);
@ -1506,31 +1423,8 @@ WebGLContext::MozGetUnderlyingParamString(uint32_t pname, nsAString& retval)
}
void
WebGLContext::ClearScreen()
{
ScopedBindFramebuffer autoFB(gl, 0);
const bool changeDrawBuffers = (mDefaultFB_DrawBuffer0 != LOCAL_GL_BACK);
if (changeDrawBuffers) {
gl->Screen()->SetDrawBuffer(LOCAL_GL_BACK);
}
GLbitfield bufferBits = LOCAL_GL_COLOR_BUFFER_BIT;
if (mOptions.depth)
bufferBits |= LOCAL_GL_DEPTH_BUFFER_BIT;
if (mOptions.stencil)
bufferBits |= LOCAL_GL_STENCIL_BUFFER_BIT;
ForceClearFramebufferWithDefaultValues(bufferBits, mNeedsFakeNoAlpha);
if (changeDrawBuffers) {
gl->Screen()->SetDrawBuffer(mDefaultFB_DrawBuffer0);
}
}
void
WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield clearBits,
bool fakeNoAlpha)
WebGLContext::ForceClearFramebufferWithDefaultValues(const GLbitfield clearBits,
const bool fakeNoAlpha) const
{
const bool initializeColorBuffer = bool(clearBits & LOCAL_GL_COLOR_BUFFER_BIT);
const bool initializeDepthBuffer = bool(clearBits & LOCAL_GL_DEPTH_BUFFER_BIT);
@ -1545,6 +1439,7 @@ WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield clearBits,
if (initializeColorBuffer) {
gl->fColorMask(1, 1, 1, 1);
mDriverColorMask = 0x0f;
if (fakeNoAlpha) {
gl->fClearColor(0.0f, 0.0f, 0.0f, 1.0f);
@ -1583,10 +1478,6 @@ WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield clearBits,
// Restore GL state after clearing.
if (initializeColorBuffer) {
gl->fColorMask(mColorWriteMask[0],
mColorWriteMask[1],
mColorWriteMask[2],
mColorWriteMask[3]);
gl->fClearColor(mColorClearValue[0],
mColorClearValue[1],
mColorClearValue[2],
@ -1616,31 +1507,81 @@ WebGLContext::OnEndOfFrame() const
gl->ResetSyncCallCount("WebGLContext PresentScreenBuffer");
}
void
WebGLContext::BlitBackbufferToCurDriverFB() const
{
if (mScissorTestEnabled) {
gl->fDisable(LOCAL_GL_SCISSOR_TEST);
}
[&]() {
const auto& size = mDefaultFB->mSize;
if (gl->IsSupported(GLFeature::framebuffer_blit)) {
gl->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, mDefaultFB->mFB);
gl->fBlitFramebuffer(0, 0, size.width, size.height,
0, 0, size.width, size.height,
LOCAL_GL_COLOR_BUFFER_BIT, LOCAL_GL_NEAREST);
return;
}
if (mDefaultFB->mSamples &&
gl->IsExtensionSupported(GLContext::APPLE_framebuffer_multisample))
{
gl->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, mDefaultFB->mFB);
gl->fResolveMultisampleFramebufferAPPLE();
return;
}
gl->BlitHelper()->DrawBlitTextureToFramebuffer(mDefaultFB->ColorTex(), size,
size);
}();
if (mScissorTestEnabled) {
gl->fEnable(LOCAL_GL_SCISSOR_TEST);
}
}
// For an overview of how WebGL compositing works, see:
// https://wiki.mozilla.org/Platform/GFX/WebGL/Compositing
bool
WebGLContext::PresentScreenBuffer()
{
if (IsContextLost()) {
if (IsContextLost())
return false;
if (!mShouldPresent)
return false;
if (!ValidateAndInitFB("Present", nullptr))
return false;
const auto& screen = gl->Screen();
if (screen->Size() != mDefaultFB->mSize &&
!screen->Resize(mDefaultFB->mSize))
{
GenerateWarning("screen->Resize failed. Losing context.");
ForceLoseContext();
return false;
}
if (!mShouldPresent) {
return false;
}
MOZ_ASSERT(!mBackbufferNeedsClear);
GLScreenBuffer* screen = gl->Screen();
MOZ_ASSERT(screen);
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
BlitBackbufferToCurDriverFB();
if (!screen->PublishFrame(screen->Size())) {
GenerateWarning("PublishFrame failed. Losing context.");
ForceLoseContext();
return false;
}
if (!mOptions.preserveDrawingBuffer) {
mBackbufferNeedsClear = true;
if (gl->IsSupported(gl::GLFeature::invalidate_framebuffer)) {
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mDefaultFB->mFB);
const GLenum attachments[] = { LOCAL_GL_COLOR_ATTACHMENT0 };
gl->fInvalidateFramebuffer(LOCAL_GL_FRAMEBUFFER, 1, attachments);
}
mDefaultFB_IsInvalid = true;
}
mResolvedDefaultFB = nullptr;
mShouldPresent = false;
OnEndOfFrame();
@ -1747,7 +1688,7 @@ CheckContextLost(GLContext* gl, bool* const out_isGuilty)
bool
WebGLContext::TryToRestoreContext()
{
if (NS_FAILED(SetDimensions(mWidth, mHeight)))
if (NS_FAILED(SetDimensions(mRequestedSize.width, mRequestedSize.height)))
return false;
return true;
@ -1959,31 +1900,18 @@ WebGLContext::GetSurfaceSnapshot(gfxAlphaType* const out_alphaType)
if (!gl)
return nullptr;
if (!BindDefaultFBForRead("GetSurfaceSnapshot"))
return nullptr;
const auto surfFormat = mOptions.alpha ? SurfaceFormat::B8G8R8A8
: SurfaceFormat::B8G8R8X8;
const auto& size = mDefaultFB->mSize;
RefPtr<DataSourceSurface> surf;
surf = Factory::CreateDataSourceSurfaceWithStride(IntSize(mWidth, mHeight),
surfFormat,
mWidth * 4);
surf = Factory::CreateDataSourceSurfaceWithStride(size, surfFormat, size.width * 4);
if (NS_WARN_IF(!surf))
return nullptr;
{
ScopedBindFramebuffer autoFB(gl, 0);
ClearBackbufferIfNeeded();
// Save, override, then restore glReadBuffer.
const GLenum readBufferMode = gl->Screen()->GetReadBufferMode();
if (readBufferMode != LOCAL_GL_BACK) {
gl->Screen()->SetReadBuffer(LOCAL_GL_BACK);
}
ReadPixelsIntoDataSurface(gl, surf);
if (readBufferMode != LOCAL_GL_BACK) {
gl->Screen()->SetReadBuffer(readBufferMode);
}
}
ReadPixelsIntoDataSurface(gl, surf);
gfxAlphaType alphaType;
if (!mOptions.alpha) {
@ -2005,17 +1933,14 @@ WebGLContext::GetSurfaceSnapshot(gfxAlphaType* const out_alphaType)
RefPtr<DrawTarget> dt =
Factory::CreateDrawTarget(gfxPlatform::GetPlatform()->GetSoftwareBackend(),
IntSize(mWidth, mHeight),
SurfaceFormat::B8G8R8A8);
size, SurfaceFormat::B8G8R8A8);
if (!dt)
return nullptr;
dt->SetTransform(Matrix::Translation(0.0, mHeight).PreScale(1.0, -1.0));
dt->SetTransform(Matrix::Translation(0.0, size.height).PreScale(1.0, -1.0));
dt->DrawSurface(surf,
Rect(0, 0, mWidth, mHeight),
Rect(0, 0, mWidth, mHeight),
DrawSurfaceOptions(),
const gfx::Rect rect{0, 0, float(size.width), float(size.height)};
dt->DrawSurface(surf, rect, rect, DrawSurfaceOptions(),
DrawOptions(1.0f, CompositionOp::OP_SOURCE));
return dt->Snapshot();
@ -2029,104 +1954,180 @@ WebGLContext::DidRefresh()
}
}
bool
WebGLContext::ValidateCurFBForRead(const char* funcName,
const webgl::FormatUsageInfo** const out_format,
uint32_t* const out_width, uint32_t* const out_height)
////////////////////////////////////////////////////////////////////////////////
gfx::IntSize
WebGLContext::DrawingBufferSize() const
{
if (!mBoundReadFramebuffer) {
const GLenum readBufferMode = gl->Screen()->GetReadBufferMode();
if (readBufferMode == LOCAL_GL_NONE) {
ErrorInvalidOperation("%s: Can't read from backbuffer when readBuffer mode is"
" NONE.",
funcName);
const gfx::IntSize zeros{0, 0};
if (IsContextLost())
return zeros;
if (!EnsureDefaultFB())
return zeros;
return mDefaultFB->mSize;
}
bool
WebGLContext::ValidateAndInitFB(const char* const funcName,
const WebGLFramebuffer* const fb)
{
if (fb)
return fb->ValidateAndInitAttachments(funcName);
if (!EnsureDefaultFB()) {
GenerateWarning("%s: Lazy resize failed. Losing context.", funcName);
ForceLoseContext();
return false;
}
if (mDefaultFB_IsInvalid) {
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mDefaultFB->mFB);
const GLbitfield bits = LOCAL_GL_COLOR_BUFFER_BIT |
LOCAL_GL_DEPTH_BUFFER_BIT |
LOCAL_GL_STENCIL_BUFFER_BIT;
const bool fakeNoAlpha = !mOptions.alpha;
ForceClearFramebufferWithDefaultValues(bits, fakeNoAlpha);
mDefaultFB_IsInvalid = false;
}
return true;
}
void
WebGLContext::DoBindFB(const WebGLFramebuffer* const fb, const GLenum target) const
{
const GLenum driverFB = fb ? fb->mGLName : mDefaultFB->mFB;
gl->fBindFramebuffer(target, driverFB);
}
bool
WebGLContext::BindCurFBForDraw(const char* const funcName)
{
const auto& fb = mBoundDrawFramebuffer;
if (!ValidateAndInitFB(funcName, fb))
return false;
DoBindFB(fb);
return true;
}
bool
WebGLContext::BindCurFBForColorRead(const char* const funcName,
const webgl::FormatUsageInfo** const out_format,
uint32_t* const out_width,
uint32_t* const out_height)
{
const auto& fb = mBoundReadFramebuffer;
if (fb) {
if (!ValidateAndInitFB(funcName, fb))
return false;
if (!fb->ValidateForColorRead(funcName, out_format, out_width, out_height))
return false;
}
ClearBackbufferIfNeeded();
// FIXME - here we're assuming that the default framebuffer is backed by
// UNSIGNED_BYTE that might not always be true, say if we had a 16bpp default
// framebuffer.
auto effFormat = mOptions.alpha ? webgl::EffectiveFormat::RGBA8
: webgl::EffectiveFormat::RGB8;
*out_format = mFormatUsage->GetUsage(effFormat);
MOZ_ASSERT(*out_format);
*out_width = mWidth;
*out_height = mHeight;
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb->mGLName);
return true;
}
return mBoundReadFramebuffer->ValidateForRead(funcName, out_format, out_width,
out_height);
if (!BindDefaultFBForRead(funcName))
return false;
if (mDefaultFB_ReadBuffer == LOCAL_GL_NONE) {
ErrorInvalidOperation("%s: Can't read from backbuffer when readBuffer mode is"
" NONE.",
funcName);
return false;
}
auto effFormat = mOptions.alpha ? webgl::EffectiveFormat::RGBA8
: webgl::EffectiveFormat::RGB8;
*out_format = mFormatUsage->GetUsage(effFormat);
MOZ_ASSERT(*out_format);
*out_width = mDefaultFB->mSize.width;
*out_height = mDefaultFB->mSize.height;
return true;
}
bool
WebGLContext::BindDefaultFBForRead(const char* const funcName)
{
if (!ValidateAndInitFB(funcName, nullptr))
return false;
if (!mDefaultFB->mSamples) {
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mDefaultFB->mFB);
return true;
}
if (!mResolvedDefaultFB) {
mResolvedDefaultFB = MozFramebuffer::Create(gl, mDefaultFB->mSize, 0, false);
if (!mResolvedDefaultFB) {
gfxCriticalNote << funcName << ": Failed to create mResolvedDefaultFB.";
return false;
}
}
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mResolvedDefaultFB->mFB);
BlitBackbufferToCurDriverFB();
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mResolvedDefaultFB->mFB);
return true;
}
////////////////////////////////////////////////////////////////////////////////
WebGLContext::ScopedDrawCallWrapper::ScopedDrawCallWrapper(WebGLContext& webgl)
ScopedDrawCallWrapper::ScopedDrawCallWrapper(WebGLContext& webgl)
: mWebGL(webgl)
, mFakeNoAlpha(ShouldFakeNoAlpha(webgl))
, mFakeNoDepth(ShouldFakeNoDepth(webgl))
, mFakeNoStencil(ShouldFakeNoStencil(webgl))
{
uint8_t driverColorMask = mWebGL.mColorWriteMask;
bool driverDepthTest = mWebGL.mDepthTestEnabled;
bool driverStencilTest = mWebGL.mStencilTestEnabled;
if (!mWebGL.mBoundDrawFramebuffer) {
mWebGL.ClearBackbufferIfNeeded();
if (mWebGL.mDefaultFB_DrawBuffer0 == LOCAL_GL_NONE) {
driverColorMask = 0; // Is this well-optimized enough for depth-first
// rendering?
} else {
driverColorMask &= ~(uint8_t(mWebGL.mNeedsFakeNoAlpha) << 3);
}
driverDepthTest &= !mWebGL.mNeedsFakeNoDepth;
driverStencilTest &= !mWebGL.mNeedsFakeNoStencil;
}
if (mFakeNoAlpha) {
mWebGL.gl->fColorMask(mWebGL.mColorWriteMask[0],
mWebGL.mColorWriteMask[1],
mWebGL.mColorWriteMask[2],
false);
const auto& gl = mWebGL.gl;
if (mWebGL.mDriverColorMask != driverColorMask) {
mWebGL.mDriverColorMask = driverColorMask;
gl->fColorMask(bool(mWebGL.mDriverColorMask & (1 << 0)),
bool(mWebGL.mDriverColorMask & (1 << 1)),
bool(mWebGL.mDriverColorMask & (1 << 2)),
bool(mWebGL.mDriverColorMask & (1 << 3)));
}
if (mFakeNoDepth) {
mWebGL.gl->fDisable(LOCAL_GL_DEPTH_TEST);
if (mWebGL.mDriverDepthTest != driverDepthTest) {
// "When disabled, the depth comparison and subsequent possible updates to the
// depth buffer value are bypassed and the fragment is passed to the next
// operation." [GLES 3.0.5, p177]
mWebGL.mDriverDepthTest = driverDepthTest;
gl->SetEnabled(LOCAL_GL_DEPTH_TEST, mWebGL.mDriverDepthTest);
}
if (mFakeNoStencil) {
mWebGL.gl->fDisable(LOCAL_GL_STENCIL_TEST);
if (mWebGL.mDriverStencilTest != driverStencilTest) {
// "When disabled, the stencil test and associated modifications are not made, and
// the fragment is always passed." [GLES 3.0.5, p175]
mWebGL.mDriverStencilTest = driverStencilTest;
gl->SetEnabled(LOCAL_GL_STENCIL_TEST, mWebGL.mDriverStencilTest);
}
}
WebGLContext::ScopedDrawCallWrapper::~ScopedDrawCallWrapper()
ScopedDrawCallWrapper::~ScopedDrawCallWrapper()
{
if (mFakeNoAlpha) {
mWebGL.gl->fColorMask(mWebGL.mColorWriteMask[0],
mWebGL.mColorWriteMask[1],
mWebGL.mColorWriteMask[2],
mWebGL.mColorWriteMask[3]);
}
if (mFakeNoDepth) {
mWebGL.gl->fEnable(LOCAL_GL_DEPTH_TEST);
}
if (mFakeNoStencil) {
MOZ_ASSERT(mWebGL.mStencilTestEnabled);
mWebGL.gl->fEnable(LOCAL_GL_STENCIL_TEST);
}
if (mWebGL.mBoundDrawFramebuffer)
return;
if (!mWebGL.mBoundDrawFramebuffer) {
mWebGL.Invalidate();
mWebGL.mShouldPresent = true;
}
}
mWebGL.mResolvedDefaultFB = nullptr;
/*static*/ bool
WebGLContext::ScopedDrawCallWrapper::HasDepthButNoStencil(const WebGLFramebuffer* fb)
{
const auto& depth = fb->DepthAttachment();
const auto& stencil = fb->StencilAttachment();
return depth.IsDefined() && !stencil.IsDefined();
}
////
void
WebGLContext::OnBeforeReadCall()
{
if (!mBoundReadFramebuffer) {
ClearBackbufferIfNeeded();
}
mWebGL.Invalidate();
mWebGL.mShouldPresent = true;
}
////////////////////////////////////////

Просмотреть файл

@ -67,6 +67,7 @@ class nsIDocShell;
namespace mozilla {
class ScopedCopyTexImageSource;
class ScopedDrawCallWrapper;
class ScopedResolveTexturesForDraw;
class ScopedUnpackReset;
class WebGLActiveInfo;
@ -98,6 +99,10 @@ class SourceSurface;
class VRLayerChild;
} // namespace gfx
namespace gl {
class MozFramebuffer;
} // namespace gl
namespace webgl {
struct LinkedProgramInfo;
class ShaderValidator;
@ -273,9 +278,9 @@ class WebGLContext
, public nsICanvasRenderingContextInternal
, public nsSupportsWeakReference
, public WebGLContextUnchecked
, public WebGLRectangleObject
, public nsWrapperCache
{
friend class ScopedDrawCallWrapper;
friend class ScopedDrawHelper;
friend class ScopedDrawWithTransformFeedback;
friend class ScopedFBRebinder;
@ -337,8 +342,8 @@ public:
virtual void OnMemoryPressure() override;
// nsICanvasRenderingContextInternal
virtual int32_t GetWidth() const override;
virtual int32_t GetHeight() const override;
virtual int32_t GetWidth() const override { return DrawingBufferWidth(); }
virtual int32_t GetHeight() const override { return DrawingBufferHeight(); }
NS_IMETHOD SetDimensions(int32_t width, int32_t height) override;
NS_IMETHOD InitializeWithDrawTarget(nsIDocShell*,
@ -381,22 +386,22 @@ public:
return NS_ERROR_NOT_IMPLEMENTED;
}
void SynthesizeGLError(GLenum err);
void SynthesizeGLError(GLenum err, const char* fmt, ...) MOZ_FORMAT_PRINTF(3, 4);
void SynthesizeGLError(GLenum err) const;
void SynthesizeGLError(GLenum err, const char* fmt, ...) const MOZ_FORMAT_PRINTF(3, 4);
void ErrorInvalidEnum(const char* fmt = 0, ...) MOZ_FORMAT_PRINTF(2, 3);
void ErrorInvalidOperation(const char* fmt = 0, ...) MOZ_FORMAT_PRINTF(2, 3);
void ErrorInvalidValue(const char* fmt = 0, ...) MOZ_FORMAT_PRINTF(2, 3);
void ErrorInvalidFramebufferOperation(const char* fmt = 0, ...) MOZ_FORMAT_PRINTF(2, 3);
void ErrorInvalidEnumInfo(const char* info, GLenum enumValue);
void ErrorInvalidEnum(const char* fmt = 0, ...) const MOZ_FORMAT_PRINTF(2, 3);
void ErrorInvalidOperation(const char* fmt = 0, ...) const MOZ_FORMAT_PRINTF(2, 3);
void ErrorInvalidValue(const char* fmt = 0, ...) const MOZ_FORMAT_PRINTF(2, 3);
void ErrorInvalidFramebufferOperation(const char* fmt = 0, ...) const MOZ_FORMAT_PRINTF(2, 3);
void ErrorInvalidEnumInfo(const char* info, GLenum enumValue) const;
void ErrorInvalidEnumInfo(const char* info, const char* funcName,
GLenum enumValue);
void ErrorOutOfMemory(const char* fmt = 0, ...) MOZ_FORMAT_PRINTF(2, 3);
void ErrorImplementationBug(const char* fmt = 0, ...) MOZ_FORMAT_PRINTF(2, 3);
GLenum enumValue) const;
void ErrorOutOfMemory(const char* fmt = 0, ...) const MOZ_FORMAT_PRINTF(2, 3);
void ErrorImplementationBug(const char* fmt = 0, ...) const MOZ_FORMAT_PRINTF(2, 3);
void ErrorInvalidEnumArg(const char* funcName, const char* argName, GLenum val);
void ErrorInvalidEnumArg(const char* funcName, const char* argName, GLenum val) const;
const char* ErrorName(GLenum error);
static const char* ErrorName(GLenum error);
/**
* Return displayable name for GLenum.
@ -477,11 +482,8 @@ public:
// amount of work it does.
// It only clears the buffers we specify, and can reset its state without
// first having to query anything, as WebGL knows its state at all times.
void ForceClearFramebufferWithDefaultValues(GLbitfield bufferBits, bool fakeNoAlpha);
// Calls ForceClearFramebufferWithDefaultValues() for the Context's 'screen'.
void ClearScreen();
void ClearBackbufferIfNeeded();
void ForceClearFramebufferWithDefaultValues(GLbitfield bufferBits,
bool fakeNoAlpha) const;
void RunContextLossTimer();
void UpdateContextLossStatus();
@ -489,8 +491,8 @@ public:
bool TryToRestoreContext();
void AssertCachedBindings();
void AssertCachedGlobalState();
void AssertCachedBindings() const;
void AssertCachedGlobalState() const;
dom::HTMLCanvasElement* GetCanvas() const { return mCanvasElement; }
nsIDocument* GetOwnerDoc() const;
@ -498,10 +500,11 @@ public:
// WebIDL WebGLRenderingContext API
void Commit();
void GetCanvas(Nullable<dom::OwningHTMLCanvasElementOrOffscreenCanvas>& retval);
GLsizei DrawingBufferWidth() const { return IsContextLost() ? 0 : mWidth; }
GLsizei DrawingBufferHeight() const {
return IsContextLost() ? 0 : mHeight;
}
private:
gfx::IntSize DrawingBufferSize() const;
public:
GLsizei DrawingBufferWidth() const { return DrawingBufferSize().width; }
GLsizei DrawingBufferHeight() const { return DrawingBufferSize().height; }
layers::LayersBackend GetCompositorBackendType() const;
@ -986,7 +989,7 @@ public:
public:
void Disable(GLenum cap);
void Enable(GLenum cap);
bool GetStencilBits(GLint* const out_stencilBits);
bool GetStencilBits(GLint* const out_stencilBits) const;
bool GetChannelBits(const char* funcName, GLenum pname, GLint* const out_val);
virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv);
@ -1443,7 +1446,6 @@ protected:
bool mCanLoseContextInForeground;
bool mRestoreWhenVisible;
bool mShouldPresent;
bool mBackbufferNeedsClear;
bool mDisableFragHighP;
template<typename WebGLObjectType>
@ -1451,12 +1453,13 @@ protected:
GLuint mActiveTexture;
GLenum mDefaultFB_DrawBuffer0;
GLenum mDefaultFB_ReadBuffer;
// glGetError sources:
bool mEmitContextLostErrorOnce;
GLenum mWebGLError;
GLenum mUnderlyingGLError;
GLenum GetAndFlushUnderlyingGLErrors();
mutable GLenum mWebGLError;
mutable GLenum mUnderlyingGLError;
GLenum GetAndFlushUnderlyingGLErrors() const;
bool mBypassShaderValidation;
@ -1585,8 +1588,6 @@ protected:
bool CreateAndInitGL(bool forceEnabled,
std::vector<FailureReason>* const out_failReasons);
bool ResizeBackbuffer(uint32_t width, uint32_t height);
typedef already_AddRefed<gl::GLContext> FnCreateGL_T(const gl::SurfaceCaps& caps,
gl::CreateContextFlags flags,
WebGLContext* webgl,
@ -1662,10 +1663,6 @@ protected:
WebGLProgram* program,
const char* funcName);
bool ValidateCurFBForRead(const char* funcName,
const webgl::FormatUsageInfo** const out_format,
uint32_t* const out_width, uint32_t* const out_height);
bool HasDrawBuffers() const {
return IsWebGL2() ||
IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers);
@ -1938,7 +1935,7 @@ protected:
GLuint mStencilValueMaskBack;
GLuint mStencilWriteMaskFront;
GLuint mStencilWriteMaskBack;
realGLboolean mColorWriteMask[4];
uint8_t mColorWriteMask; // bitmask
realGLboolean mDepthWriteMask;
GLfloat mColorClearValue[4];
GLint mStencilClearValue;
@ -1962,7 +1959,7 @@ protected:
// be Flushed while doing hundreds of draw calls.
int mDrawCallsSinceLastFlush;
int mAlreadyGeneratedWarnings;
mutable int mAlreadyGeneratedWarnings;
int mMaxWarnings;
bool mAlreadyWarnedAboutFakeVertexAttrib0;
@ -1977,7 +1974,10 @@ protected:
bool mNeedsFakeNoAlpha;
bool mNeedsFakeNoDepth;
bool mNeedsFakeNoStencil;
bool mNeedsEmulatedLoneDepthStencil;
mutable uint8_t mDriverColorMask;
bool mDriverDepthTest;
bool mDriverStencilTest;
bool mNeedsIndexValidation;
@ -1985,63 +1985,30 @@ protected:
bool Has64BitTimestamps() const;
struct ScopedDrawCallWrapper final {
WebGLContext& mWebGL;
const bool mFakeNoAlpha;
const bool mFakeNoDepth;
const bool mFakeNoStencil;
// --
static bool ShouldFakeNoAlpha(WebGLContext& webgl) {
// We should only be doing this if we're about to draw to the backbuffer, but
// the backbuffer needs to have this fake-no-alpha workaround.
return !webgl.mBoundDrawFramebuffer &&
webgl.mNeedsFakeNoAlpha &&
webgl.mColorWriteMask[3] != false;
}
const uint8_t mMsaaSamples;
gfx::IntSize mRequestedSize;
mutable UniquePtr<gl::MozFramebuffer> mDefaultFB;
mutable bool mDefaultFB_IsInvalid;
mutable UniquePtr<gl::MozFramebuffer> mResolvedDefaultFB;
static bool ShouldFakeNoDepth(WebGLContext& webgl) {
// We should only be doing this if we're about to draw to the backbuffer.
return !webgl.mBoundDrawFramebuffer &&
webgl.mNeedsFakeNoDepth &&
webgl.mDepthTestEnabled;
}
// --
static bool HasDepthButNoStencil(const WebGLFramebuffer* fb);
bool EnsureDefaultFB() const;
bool ValidateAndInitFB(const char* funcName, const WebGLFramebuffer* fb);
void DoBindFB(const WebGLFramebuffer* fb, GLenum target = LOCAL_GL_FRAMEBUFFER) const;
static bool ShouldFakeNoStencil(WebGLContext& webgl) {
if (!webgl.mStencilTestEnabled)
return false;
bool BindCurFBForDraw(const char* funcName);
bool BindCurFBForColorRead(const char* funcName,
const webgl::FormatUsageInfo** out_format,
uint32_t* out_width, uint32_t* out_height);
void BlitBackbufferToCurDriverFB() const;
bool BindDefaultFBForRead(const char* funcName);
if (!webgl.mBoundDrawFramebuffer) {
if (webgl.mNeedsFakeNoStencil)
return true;
if (webgl.mNeedsEmulatedLoneDepthStencil &&
webgl.mOptions.depth && !webgl.mOptions.stencil)
{
return true;
}
return false;
}
if (webgl.mNeedsEmulatedLoneDepthStencil &&
HasDepthButNoStencil(webgl.mBoundDrawFramebuffer))
{
return true;
}
return false;
}
////
explicit ScopedDrawCallWrapper(WebGLContext& webgl);
~ScopedDrawCallWrapper();
};
void OnBeforeReadCall();
// --
public:
void LoseOldestWebGLContextIfLimitExceeded();
void UpdateLastUseIndex();
@ -2063,8 +2030,8 @@ protected:
public:
// console logging helpers
void GenerateWarning(const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3);
void GenerateWarning(const char* fmt, va_list ap) MOZ_FORMAT_PRINTF(2, 0);
void GenerateWarning(const char* fmt, ...) const MOZ_FORMAT_PRINTF(2, 3);
void GenerateWarning(const char* fmt, va_list ap) const MOZ_FORMAT_PRINTF(2, 0);
void GeneratePerfWarning(const char* fmt, ...) const MOZ_FORMAT_PRINTF(2, 3);
@ -2190,6 +2157,17 @@ AvailGroups(uint64_t totalAvailItems, uint64_t firstItemOffset, uint32_t groupSi
////
class ScopedDrawCallWrapper final
{
public:
WebGLContext& mWebGL;
explicit ScopedDrawCallWrapper(WebGLContext& webgl);
~ScopedDrawCallWrapper();
};
////
void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
const std::vector<IndexedBufferBinding>& field,

Просмотреть файл

@ -6,6 +6,7 @@
#include "WebGLContext.h"
#include "GeckoProfiler.h"
#include "gfx/gl/MozFramebuffer.h"
#include "GLContext.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/UniquePtrExtensions.h"
@ -99,23 +100,10 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw(WebGLContext* webgl,
{
MOZ_ASSERT(mWebGL->gl->IsCurrent());
if (!mWebGL->mActiveProgramLinkInfo) {
mWebGL->ErrorInvalidOperation("%s: The current program is not linked.", funcName);
*out_error = true;
return;
}
const std::vector<const WebGLFBAttachPoint*>* attachList = nullptr;
const auto& fb = mWebGL->mBoundDrawFramebuffer;
if (fb) {
if (!fb->ValidateAndInitAttachments(funcName)) {
*out_error = true;
return;
}
attachList = &(fb->ResolvedCompleteData()->texDrawBuffers);
} else {
webgl->ClearBackbufferIfNeeded();
}
MOZ_ASSERT(mWebGL->mActiveProgramLinkInfo);
@ -255,6 +243,11 @@ public:
{
MOZ_ASSERT(mWebGL->gl->IsCurrent());
if (!mWebGL->BindCurFBForDraw(funcName)) {
*out_error = true;
return;
}
if (!mWebGL->ValidateDrawModeEnum(mode, funcName)) {
*out_error = true;
return;
@ -265,22 +258,16 @@ public:
return;
}
////
if (mWebGL->mBoundDrawFramebuffer) {
if (!mWebGL->mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName)) {
*out_error = true;
return;
}
} else {
mWebGL->ClearBackbufferIfNeeded();
if (!mWebGL->mActiveProgramLinkInfo) {
mWebGL->ErrorInvalidOperation("%s: The current program is not linked.", funcName);
*out_error = true;
return;
}
const auto& linkInfo = mWebGL->mActiveProgramLinkInfo;
////
// Check UBO sizes.
const auto& linkInfo = mWebGL->mActiveProgramLinkInfo;
for (const auto& cur : linkInfo->uniformBlocks) {
const auto& dataSize = cur->mDataSize;
const auto& binding = cur->mBinding;
@ -525,20 +512,20 @@ WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei vertCount,
if (IsContextLost())
return;
bool error = false;
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error)
return;
Maybe<uint32_t> lastVert;
if (!DrawArrays_check(funcName, first, vertCount, instanceCount, &lastVert))
return;
bool error = false;
const ScopedDrawHelper scopedHelper(this, funcName, mode, lastVert, instanceCount,
&error);
if (error)
return;
const ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error)
return;
const ScopedDrawWithTransformFeedback scopedTF(this, funcName, mode, vertCount,
instanceCount, &error);
if (error)
@ -681,11 +668,6 @@ WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei indexCount, GLenum type
if (IsContextLost())
return;
bool error = false;
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error)
return;
Maybe<uint32_t> lastVert;
if (!DrawElements_check(funcName, indexCount, type, byteOffset, instanceCount,
&lastVert))
@ -693,11 +675,16 @@ WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei indexCount, GLenum type
return;
}
bool error = false;
const ScopedDrawHelper scopedHelper(this, funcName, mode, lastVert, instanceCount,
&error);
if (error)
return;
const ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error)
return;
{
ScopedDrawCallWrapper wrapper(*this);
{
@ -759,8 +746,8 @@ WebGLContext::Draw_cleanup(const char* funcName)
break;
}
} else {
destWidth = mWidth;
destHeight = mHeight;
destWidth = mDefaultFB->mSize.width;
destHeight = mDefaultFB->mSize.height;
}
if (mViewportWidth > int32_t(destWidth) ||

Просмотреть файл

@ -30,10 +30,7 @@ WebGLContext::Clear(GLbitfield mask)
GenerateWarning("Calling gl.clear() with RASTERIZER_DISCARD enabled has no effects.");
}
if (mBoundDrawFramebuffer) {
if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName))
return;
if (mask & LOCAL_GL_COLOR_BUFFER_BIT && mBoundDrawFramebuffer) {
if (mask & LOCAL_GL_COLOR_BUFFER_BIT) {
for (const auto& cur : mBoundDrawFramebuffer->ColorDrawBuffers()) {
if (!cur->IsDefined())
@ -55,8 +52,21 @@ WebGLContext::Clear(GLbitfield mask)
}
}
ScopedDrawCallWrapper wrapper(*this);
gl->fClear(mask);
if (!BindCurFBForDraw(funcName))
return;
auto driverMask = mask;
if (!mBoundDrawFramebuffer) {
if (mNeedsFakeNoDepth) {
driverMask &= ~LOCAL_GL_DEPTH_BUFFER_BIT;
}
if (mNeedsFakeNoStencil) {
driverMask &= ~LOCAL_GL_STENCIL_BUFFER_BIT;
}
}
const ScopedDrawCallWrapper wrapper(*this);
gl->fClear(driverMask);
}
static GLfloat
@ -121,11 +131,11 @@ WebGLContext::ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboo
if (IsContextLost())
return;
mColorWriteMask[0] = r;
mColorWriteMask[1] = g;
mColorWriteMask[2] = b;
mColorWriteMask[3] = a;
gl->fColorMask(r, g, b, a);
mColorWriteMask = uint8_t(bool(r)) << 0 |
uint8_t(bool(g)) << 1 |
uint8_t(bool(b)) << 2 |
uint8_t(bool(a)) << 3;
}
void
@ -175,7 +185,7 @@ WebGLContext::DrawBuffers(const dom::Sequence<GLenum>& buffers)
}
mDefaultFB_DrawBuffer0 = buffers[0];
gl->Screen()->SetDrawBuffer(buffers[0]);
// Don't actually set it.
}
void

Просмотреть файл

@ -1561,7 +1561,7 @@ WebGLContext::ReadPixelsImpl(GLint x, GLint y, GLsizei rawWidth, GLsizei rawHeig
const webgl::FormatUsageInfo* srcFormat;
uint32_t srcWidth;
uint32_t srcHeight;
if (!ValidateCurFBForRead("readPixels", &srcFormat, &srcWidth, &srcHeight))
if (!BindCurFBForColorRead("readPixels", &srcFormat, &srcWidth, &srcHeight))
return;
//////
@ -1606,8 +1606,6 @@ WebGLContext::ReadPixelsImpl(GLint x, GLint y, GLsizei rawWidth, GLsizei rawHeig
////////////////
// Now that the errors are out of the way, on to actually reading!
OnBeforeReadCall();
if (!rwWidth || !rwHeight) {
// Disjoint rects, so we're done already.
DummyReadFramebufferOperation("readPixels");

Просмотреть файл

@ -60,7 +60,7 @@ WebGLContext::Enable(GLenum cap)
}
bool
WebGLContext::GetStencilBits(GLint* const out_stencilBits)
WebGLContext::GetStencilBits(GLint* const out_stencilBits) const
{
*out_stencilBits = 0;
if (mBoundDrawFramebuffer) {
@ -190,7 +190,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
GLint ret = LOCAL_GL_NONE;
if (!mBoundDrawFramebuffer) {
if (pname == LOCAL_GL_DRAW_BUFFER0) {
ret = gl->Screen()->GetDrawBufferMode();
ret = mDefaultFB_DrawBuffer0;
}
} else {
gl->fGetIntegerv(pname, &ret);
@ -342,7 +342,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
case LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE: {
const webgl::FormatUsageInfo* usage;
uint32_t width, height;
if (!ValidateCurFBForRead(funcName, &usage, &width, &height))
if (!BindCurFBForColorRead(funcName, &usage, &width, &height))
return JS::NullValue();
const auto implPI = ValidImplementationColorReadPI(usage);

Просмотреть файл

@ -56,7 +56,7 @@ StringValue(JSContext* cx, const char* chars, ErrorResult& rv)
}
void
WebGLContext::GenerateWarning(const char* fmt, ...)
WebGLContext::GenerateWarning(const char* fmt, ...) const
{
va_list ap;
va_start(ap, fmt);
@ -67,7 +67,7 @@ WebGLContext::GenerateWarning(const char* fmt, ...)
}
void
WebGLContext::GenerateWarning(const char* fmt, va_list ap)
WebGLContext::GenerateWarning(const char* fmt, va_list ap) const
{
if (!ShouldGenerateWarnings())
return;
@ -146,7 +146,7 @@ WebGLContext::GeneratePerfWarning(const char* fmt, ...) const
}
void
WebGLContext::SynthesizeGLError(GLenum err)
WebGLContext::SynthesizeGLError(GLenum err) const
{
/* ES2 section 2.5 "GL Errors" states that implementations can have
* multiple 'flags', as errors might be caught in different parts of
@ -159,7 +159,7 @@ WebGLContext::SynthesizeGLError(GLenum err)
}
void
WebGLContext::SynthesizeGLError(GLenum err, const char* fmt, ...)
WebGLContext::SynthesizeGLError(GLenum err, const char* fmt, ...) const
{
va_list va;
va_start(va, fmt);
@ -170,7 +170,7 @@ WebGLContext::SynthesizeGLError(GLenum err, const char* fmt, ...)
}
void
WebGLContext::ErrorInvalidEnum(const char* fmt, ...)
WebGLContext::ErrorInvalidEnum(const char* fmt, ...) const
{
va_list va;
va_start(va, fmt);
@ -181,7 +181,7 @@ WebGLContext::ErrorInvalidEnum(const char* fmt, ...)
}
void
WebGLContext::ErrorInvalidEnumInfo(const char* info, GLenum enumValue)
WebGLContext::ErrorInvalidEnumInfo(const char* info, GLenum enumValue) const
{
nsCString name;
EnumName(enumValue, &name);
@ -191,7 +191,7 @@ WebGLContext::ErrorInvalidEnumInfo(const char* info, GLenum enumValue)
void
WebGLContext::ErrorInvalidEnumInfo(const char* info, const char* funcName,
GLenum enumValue)
GLenum enumValue) const
{
nsCString name;
EnumName(enumValue, &name);
@ -201,7 +201,7 @@ WebGLContext::ErrorInvalidEnumInfo(const char* info, const char* funcName,
}
void
WebGLContext::ErrorInvalidOperation(const char* fmt, ...)
WebGLContext::ErrorInvalidOperation(const char* fmt, ...) const
{
va_list va;
va_start(va, fmt);
@ -212,7 +212,7 @@ WebGLContext::ErrorInvalidOperation(const char* fmt, ...)
}
void
WebGLContext::ErrorInvalidValue(const char* fmt, ...)
WebGLContext::ErrorInvalidValue(const char* fmt, ...) const
{
va_list va;
va_start(va, fmt);
@ -223,7 +223,7 @@ WebGLContext::ErrorInvalidValue(const char* fmt, ...)
}
void
WebGLContext::ErrorInvalidFramebufferOperation(const char* fmt, ...)
WebGLContext::ErrorInvalidFramebufferOperation(const char* fmt, ...) const
{
va_list va;
va_start(va, fmt);
@ -234,7 +234,7 @@ WebGLContext::ErrorInvalidFramebufferOperation(const char* fmt, ...)
}
void
WebGLContext::ErrorOutOfMemory(const char* fmt, ...)
WebGLContext::ErrorOutOfMemory(const char* fmt, ...) const
{
va_list va;
va_start(va, fmt);
@ -245,7 +245,7 @@ WebGLContext::ErrorOutOfMemory(const char* fmt, ...)
}
void
WebGLContext::ErrorImplementationBug(const char* fmt, ...)
WebGLContext::ErrorImplementationBug(const char* fmt, ...) const
{
const nsPrintfCString warning("Implementation bug, please file at %s! %s",
"https://bugzilla.mozilla.org/", fmt);
@ -260,7 +260,7 @@ WebGLContext::ErrorImplementationBug(const char* fmt, ...)
return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
}
const char*
/*static*/ const char*
WebGLContext::ErrorName(GLenum error)
{
switch(error) {
@ -625,7 +625,8 @@ WebGLContext::EnumName(GLenum val, nsCString* out_name)
}
void
WebGLContext::ErrorInvalidEnumArg(const char* funcName, const char* argName, GLenum val)
WebGLContext::ErrorInvalidEnumArg(const char* funcName, const char* argName,
GLenum val) const
{
nsCString enumName;
EnumName(val, &enumName);
@ -676,7 +677,7 @@ IsTextureFormatCompressed(TexInternalFormat format)
}
GLenum
WebGLContext::GetAndFlushUnderlyingGLErrors()
WebGLContext::GetAndFlushUnderlyingGLErrors() const
{
// Get and clear GL error in ALL cases.
GLenum error = gl->fGetError();
@ -739,7 +740,7 @@ AssertUintParamCorrect(gl::GLContext*, GLenum, GLuint)
#endif
void
WebGLContext::AssertCachedBindings()
WebGLContext::AssertCachedBindings() const
{
#ifdef DEBUG
GetAndFlushUnderlyingGLErrors();
@ -749,21 +750,6 @@ WebGLContext::AssertCachedBindings()
AssertUintParamCorrect(gl, LOCAL_GL_VERTEX_ARRAY_BINDING, bound);
}
// Framebuffers
if (IsWebGL2()) {
GLuint bound = mBoundDrawFramebuffer ? mBoundDrawFramebuffer->mGLName
: 0;
AssertUintParamCorrect(gl, LOCAL_GL_DRAW_FRAMEBUFFER_BINDING, bound);
bound = mBoundReadFramebuffer ? mBoundReadFramebuffer->mGLName : 0;
AssertUintParamCorrect(gl, LOCAL_GL_READ_FRAMEBUFFER_BINDING, bound);
} else {
MOZ_ASSERT(mBoundDrawFramebuffer == mBoundReadFramebuffer);
GLuint bound = mBoundDrawFramebuffer ? mBoundDrawFramebuffer->mGLName
: 0;
AssertUintParamCorrect(gl, LOCAL_GL_FRAMEBUFFER_BINDING, bound);
}
GLint stencilBits = 0;
if (GetStencilBits(&stencilBits)) { // Depends on current draw framebuffer.
const GLuint stencilRefMask = (1 << stencilBits) - 1;
@ -804,7 +790,7 @@ WebGLContext::AssertCachedBindings()
}
void
WebGLContext::AssertCachedGlobalState()
WebGLContext::AssertCachedGlobalState() const
{
#ifdef DEBUG
GetAndFlushUnderlyingGLErrors();
@ -812,19 +798,10 @@ WebGLContext::AssertCachedGlobalState()
////////////////
// Draw state
MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_DEPTH_TEST) == mDepthTestEnabled);
MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_DITHER) == mDitherEnabled);
MOZ_ASSERT_IF(IsWebGL2(),
gl->fIsEnabled(LOCAL_GL_RASTERIZER_DISCARD) == mRasterizerDiscardEnabled);
MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST) == mScissorTestEnabled);
MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_STENCIL_TEST) == mStencilTestEnabled);
realGLboolean colorWriteMask[4] = {0, 0, 0, 0};
gl->fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask);
MOZ_ASSERT(colorWriteMask[0] == mColorWriteMask[0] &&
colorWriteMask[1] == mColorWriteMask[1] &&
colorWriteMask[2] == mColorWriteMask[2] &&
colorWriteMask[3] == mColorWriteMask[3]);
GLfloat colorClearValue[4] = {0.0f, 0.0f, 0.0f, 0.0f};
gl->fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue);

Просмотреть файл

@ -420,15 +420,13 @@ WebGLContext::InitAndValidateGL(FailureReason* const out_failReason)
// These are the default values, see 6.2 State tables in the
// OpenGL ES 2.0.25 spec.
mColorWriteMask[0] = 1;
mColorWriteMask[1] = 1;
mColorWriteMask[2] = 1;
mColorWriteMask[3] = 1;
mDepthWriteMask = 1;
mColorWriteMask = 0x0f;
mDriverColorMask = mColorWriteMask;
mColorClearValue[0] = 0.f;
mColorClearValue[1] = 0.f;
mColorClearValue[2] = 0.f;
mColorClearValue[3] = 0.f;
mDepthWriteMask = true;
mDepthClearValue = 1.f;
mStencilClearValue = 0;
mStencilRefFront = 0;
@ -461,13 +459,18 @@ WebGLContext::InitAndValidateGL(FailureReason* const out_failReason)
mDitherEnabled = true;
mRasterizerDiscardEnabled = false;
mScissorTestEnabled = false;
mDepthTestEnabled = 0;
mDriverDepthTest = false;
mStencilTestEnabled = 0;
mDriverStencilTest = false;
mGenerateMipmapHint = LOCAL_GL_DONT_CARE;
// Bindings, etc.
mActiveTexture = 0;
mDefaultFB_DrawBuffer0 = LOCAL_GL_BACK;
mDefaultFB_ReadBuffer = LOCAL_GL_BACK;
mEmitContextLostErrorOnce = true;
mWebGLError = LOCAL_GL_NO_ERROR;

Просмотреть файл

@ -889,7 +889,7 @@ WebGLFramebuffer::PrecheckFramebufferStatus(nsCString* const out_info) const
// Validation
bool
WebGLFramebuffer::ValidateAndInitAttachments(const char* funcName)
WebGLFramebuffer::ValidateAndInitAttachments(const char* funcName) const
{
MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
mContext->mBoundReadFramebuffer == this);
@ -942,13 +942,11 @@ WebGLFramebuffer::ValidateClearBufferType(const char* funcName, GLenum buffer,
}
bool
WebGLFramebuffer::ValidateForRead(const char* funcName,
const webgl::FormatUsageInfo** const out_format,
uint32_t* const out_width, uint32_t* const out_height)
WebGLFramebuffer::ValidateForColorRead(const char* funcName,
const webgl::FormatUsageInfo** const out_format,
uint32_t* const out_width,
uint32_t* const out_height) const
{
if (!ValidateAndInitAttachments(funcName))
return false;
if (!mColorReadBuffer) {
mContext->ErrorInvalidOperation("%s: READ_BUFFER must not be NONE.", funcName);
return false;
@ -1185,7 +1183,7 @@ WebGLFramebuffer::RefreshResolvedData()
// Entrypoints
FBStatus
WebGLFramebuffer::CheckFramebufferStatus(const char* funcName)
WebGLFramebuffer::CheckFramebufferStatus(const char* const funcName) const
{
if (IsResolvedComplete())
return LOCAL_GL_FRAMEBUFFER_COMPLETE;
@ -1651,15 +1649,16 @@ GetBackbufferFormats(const WebGLContext* webgl,
/*static*/ void
WebGLFramebuffer::BlitFramebuffer(WebGLContext* webgl,
const WebGLFramebuffer* srcFB, GLint srcX0, GLint srcY0,
GLint srcX1, GLint srcY1,
const WebGLFramebuffer* dstFB, GLint dstX0, GLint dstY0,
GLint dstX1, GLint dstY1,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
const char funcName[] = "blitFramebuffer";
const auto& gl = webgl->gl;
const auto& srcFB = webgl->mBoundReadFramebuffer;
const auto& dstFB = webgl->mBoundDrawFramebuffer;
////
// Collect data
@ -1928,8 +1927,7 @@ WebGLFramebuffer::BlitFramebuffer(WebGLContext* webgl,
////
webgl->OnBeforeReadCall();
WebGLContext::ScopedDrawCallWrapper wrapper(*webgl);
const ScopedDrawCallWrapper wrapper(*webgl);
gl->fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1,
mask, filter);

Просмотреть файл

@ -195,7 +195,7 @@ protected:
explicit ResolvedData(const WebGLFramebuffer& parent);
};
UniquePtr<const ResolvedData> mResolvedCompleteData;
mutable UniquePtr<const ResolvedData> mResolvedCompleteData;
////
@ -236,13 +236,13 @@ protected:
public:
void DetachTexture(const char* funcName, const WebGLTexture* tex);
void DetachRenderbuffer(const char* funcName, const WebGLRenderbuffer* rb);
bool ValidateAndInitAttachments(const char* funcName);
bool ValidateAndInitAttachments(const char* funcName) const;
bool ValidateClearBufferType(const char* funcName, GLenum buffer, uint32_t drawBuffer,
GLenum funcType) const;
bool ValidateForRead(const char* info,
const webgl::FormatUsageInfo** const out_format,
uint32_t* const out_width, uint32_t* const out_height);
bool ValidateForColorRead(const char* funcName,
const webgl::FormatUsageInfo** out_format,
uint32_t* out_width, uint32_t* out_height) const;
////////////////
// Getters
@ -268,7 +268,7 @@ public:
////////////////
// WebGL funcs
FBStatus CheckFramebufferStatus(const char* funcName);
FBStatus CheckFramebufferStatus(const char* funcName) const;
void FramebufferRenderbuffer(const char* funcName, GLenum attachment, GLenum rbtarget,
WebGLRenderbuffer* rb);
void FramebufferTexture2D(const char* funcName, GLenum attachment,
@ -283,10 +283,8 @@ public:
ErrorResult* const out_error);
static void BlitFramebuffer(WebGLContext* webgl,
const WebGLFramebuffer* src, GLint srcX0, GLint srcY0,
GLint srcX1, GLint srcY1,
const WebGLFramebuffer* dst, GLint dstX0, GLint dstY0,
GLint dstX1, GLint dstY1,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
};

Просмотреть файл

@ -2121,8 +2121,8 @@ WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level, GLenum internal
const webgl::FormatUsageInfo* srcUsage;
uint32_t srcTotalWidth;
uint32_t srcTotalHeight;
if (!mContext->ValidateCurFBForRead(funcName, &srcUsage, &srcTotalWidth,
&srcTotalHeight))
if (!mContext->BindCurFBForColorRead(funcName, &srcUsage, &srcTotalWidth,
&srcTotalHeight))
{
return;
}
@ -2155,8 +2155,6 @@ WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level, GLenum internal
////////////////////////////////////
// Do the thing!
mContext->OnBeforeReadCall();
const bool isSubImage = false;
if (!DoCopyTexOrSubImage(mContext, funcName, isSubImage, this, target, level, x, y,
srcTotalWidth, srcTotalHeight, srcUsage, 0, 0, 0, width,
@ -2215,8 +2213,8 @@ WebGLTexture::CopyTexSubImage(const char* funcName, TexImageTarget target, GLint
const webgl::FormatUsageInfo* srcUsage;
uint32_t srcTotalWidth;
uint32_t srcTotalHeight;
if (!mContext->ValidateCurFBForRead(funcName, &srcUsage, &srcTotalWidth,
&srcTotalHeight))
if (!mContext->BindCurFBForColorRead(funcName, &srcUsage, &srcTotalWidth,
&srcTotalHeight))
{
return;
}
@ -2234,8 +2232,6 @@ WebGLTexture::CopyTexSubImage(const char* funcName, TexImageTarget target, GLint
////////////////////////////////////
// Do the thing!
mContext->OnBeforeReadCall();
bool uploadWillInitialize;
if (!EnsureImageDataInitializedForUpload(this, funcName, target, level, xOffset,
yOffset, zOffset, width, height, depth,

Просмотреть файл

@ -201,6 +201,7 @@ include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'../workers',
'/', # Allow including relpaths from root.
'/dom/base',
'/dom/html',
'/dom/svg',

Просмотреть файл

@ -2520,8 +2520,6 @@ GLContext::Readback(SharedSurface* src, gfx::DataSourceSurface* dest)
{
MOZ_ASSERT(src && dest);
MOZ_ASSERT(dest->GetSize() == src->mSize);
MOZ_ASSERT(dest->GetFormat() == (src->mHasAlpha ? SurfaceFormat::B8G8R8A8
: SurfaceFormat::B8G8R8X8));
if (!MakeCurrent()) {
return false;

Просмотреть файл

@ -155,8 +155,8 @@ CopyableCanvasRenderer::ReadbackSurface()
}
IntSize readSize(frontbuffer->mSize);
SurfaceFormat format =
mOpaque ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
SurfaceFormat format = frontbuffer->mHasAlpha ? SurfaceFormat::B8G8R8X8
: SurfaceFormat::B8G8R8A8;
bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
RefPtr<DataSourceSurface> resultSurf = GetTempSurface(readSize, format);

Просмотреть файл

@ -51,7 +51,6 @@ ShareableCanvasRenderer::Initialize(const CanvasInitializeData& aData)
MOZ_ASSERT(screen);
caps = screen->mCaps;
}
MOZ_ASSERT(caps.alpha == aData.mHasAlpha);
auto forwarder = GetForwarder();

Просмотреть файл

@ -755,6 +755,7 @@ private:
DECL_GFX_PREF(Live, "webgl.max-warnings-per-context", WebGLMaxWarningsPerContext, uint32_t, 32);
DECL_GFX_PREF(Live, "webgl.min_capability_mode", WebGLMinCapabilityMode, bool, false);
DECL_GFX_PREF(Live, "webgl.msaa-force", WebGLForceMSAA, bool, false);
DECL_GFX_PREF(Live, "webgl.msaa-samples", WebGLMsaaSamples, uint32_t, 4);
DECL_GFX_PREF(Live, "webgl.prefer-16bpp", WebGLPrefer16bpp, bool, false);
DECL_GFX_PREF(Live, "webgl.restore-context-when-visible", WebGLRestoreWhenVisible, bool, true);
DECL_GFX_PREF(Live, "webgl.allow-immediate-queries", WebGLImmediateQueries, bool, false);