зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1427668 - Move the webgl backbuffer into webgl. - r=daoshengmu
MozReview-Commit-ID: 2WpG7mfMRQ8
This commit is contained in:
Родитель
3f0aacfb10
Коммит
df8e8db803
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче