Bug 1754130 - Implement SharedContext for sharing WebGL state among many DrawTargetWebgls. r=aosmond

Within DrawTargetWebgl, this implements a SharedContext class to store both the WebGL context and
also related resources for drawing with it. Not a lot of new code has actually been added as this
was mostly accomplished by refactoring as much drawing code as possible that touched the WebGL
context to be moved into SharedContext, while leaving any code that was only dealing with Skia
software rasterization still within DrawTargetWebgl itself as well as individual framebuffer state
that is unique to each DrawTargetWebgl instance.

Before DrawTargetWebgl can use SharedContext to draw, it must use SetTarget to install its framebuffer
as the one that the WebGL context will draw to as well as to learn details about the viewport and
other per-framebuffer state. All of the high-level cache state that was previously on DrawTargetWebgl
has now moved into SharedContext, so that SharedContext can easily access this for drawing as well
as to provide for the goal of simplifying resource limiting.

Differential Revision: https://phabricator.services.mozilla.com/D138117
This commit is contained in:
Lee Salzman 2022-02-11 19:49:55 +00:00
parent 48d8ec73b7
commit 8346a766e0
4 changed files with 791 additions and 476 deletions

File diff suppressed because it is too large Load Diff

View File

@ -9,17 +9,24 @@
#include "mozilla/gfx/2D.h"
#include "mozilla/LinkedList.h"
#include "mozilla/WeakPtr.h"
#include <vector>
namespace mozilla {
class ClientWebGLContext;
class WebGLBufferJS;
class WebGLFramebufferJS;
class WebGLProgramJS;
class WebGLRenderbufferJS;
class WebGLTextureJS;
class WebGLUniformLocationJS;
class WebGLVertexArrayJS;
namespace layers {
class SurfaceDescriptor;
}
namespace gfx {
class DataSourceSurface;
@ -40,17 +47,22 @@ class PathCache;
// they can be accelerated where possible by WebGL. It manages both routing to
// appropriate shaders and texture allocation/caching for surfaces. For commands
// that are not feasible to accelerate with WebGL, it mirrors state to a backup
// DrawTargetSkia that can be used as a fallback software renderer.
class DrawTargetWebgl : public DrawTarget {
// DrawTargetSkia that can be used as a fallback software renderer. Multiple
// instances of DrawTargetWebgl within a process will actually share a single
// WebGL context so that data can be more easily interchanged between them and
// also to enable more reasonable limiting of resource usage.
class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr {
friend class SharedTextureHandle;
friend class StandaloneTexture;
friend class TextureHandle;
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetWebgl, override)
private:
IntSize mSize;
RefPtr<ClientWebGLContext> mWebgl;
RefPtr<WebGLFramebufferJS> mFramebuffer;
RefPtr<WebGLTextureJS> mTex;
RefPtr<DrawTargetSkia> mSkia;
// The currently cached snapshot of the WebGL context
RefPtr<DataSourceSurface> mSnapshot;
@ -60,44 +72,132 @@ class DrawTargetWebgl : public DrawTarget {
bool mSkiaLayer = false;
// Whether or not the WebGL context has valid contents and is being drawn to
bool mWebglValid = false;
// Whether or not the clip state has changed since last used by SharedContext.
bool mClipDirty = true;
// WebGL shader resources
RefPtr<WebGLBufferJS> mVertexBuffer;
RefPtr<WebGLVertexArrayJS> mVertexArray;
RefPtr<WebGLProgramJS> mSolidProgram;
RefPtr<WebGLUniformLocationJS> mSolidProgramTransform;
RefPtr<WebGLUniformLocationJS> mSolidProgramColor;
RefPtr<WebGLProgramJS> mImageProgram;
RefPtr<WebGLUniformLocationJS> mImageProgramTransform;
RefPtr<WebGLUniformLocationJS> mImageProgramTexMatrix;
RefPtr<WebGLUniformLocationJS> mImageProgramTexBounds;
RefPtr<WebGLUniformLocationJS> mImageProgramColor;
RefPtr<WebGLUniformLocationJS> mImageProgramSwizzle;
RefPtr<WebGLUniformLocationJS> mImageProgramSampler;
// A most-recently-used list of allocated texture handles.
LinkedList<RefPtr<TextureHandle>> mTextureHandles;
size_t mNumTextureHandles = 0;
// User data key linking a SourceSurface with its TextureHandle.
UserDataKey mTextureHandleKey = {0};
// User data key linking a SourceSurface with its shadow blur TextureHandle.
UserDataKey mShadowTextureKey = {0};
// User data key linking a ScaledFont with its GlyphCache.
UserDataKey mGlyphCacheKey = {0};
// List of all GlyphCaches currently allocated to fonts.
LinkedList<GlyphCache> mGlyphCaches;
// Cache of rasterized paths.
UniquePtr<PathCache> mPathCache;
// Collection of allocated shared texture pages that may be shared amongst
// many handles.
std::vector<RefPtr<SharedTexture>> mSharedTextures;
// Collection of allocated standalone textures that have a single assigned
// handle.
std::vector<RefPtr<StandaloneTexture>> mStandaloneTextures;
size_t mUsedTextureMemory = 0;
size_t mTotalTextureMemory = 0;
RefPtr<TextureHandle> mSnapshotTexture;
CompositionOp mLastCompositionOp = CompositionOp::OP_SOURCE;
uint32_t mMaxTextureSize = 0;
// SharedContext stores most of the actual WebGL state that may be used by
// any number of DrawTargetWebgl's that use it. Foremost, it holds the actual
// WebGL client context, programs, and buffers for mapping to WebGL.
// Secondarily, it holds shared caches for surfaces, glyphs, paths, and
// shadows so that each DrawTargetWebgl does not require its own cache. It is
// important that SetTarget is called to install the current DrawTargetWebgl
// before actually using the SharedContext, as the individual framebuffers
// and viewport are still maintained in DrawTargetWebgl itself.
class SharedContext : public mozilla::RefCounted<SharedContext>,
public mozilla::SupportsWeakPtr {
public:
MOZ_DECLARE_REFCOUNTED_TYPENAME(SharedContext)
SharedContext();
~SharedContext();
WeakPtr<DrawTargetWebgl> mCurrentTarget;
IntSize mViewportSize;
IntRect mClipRect;
RefPtr<ClientWebGLContext> mWebgl;
// Avoid spurious state changes by caching last used state.
RefPtr<WebGLProgramJS> mLastProgram;
RefPtr<WebGLTextureJS> mLastTexture;
// WebGL shader resources
RefPtr<WebGLBufferJS> mVertexBuffer;
RefPtr<WebGLVertexArrayJS> mVertexArray;
RefPtr<WebGLProgramJS> mSolidProgram;
RefPtr<WebGLUniformLocationJS> mSolidProgramTransform;
RefPtr<WebGLUniformLocationJS> mSolidProgramColor;
RefPtr<WebGLProgramJS> mImageProgram;
RefPtr<WebGLUniformLocationJS> mImageProgramTransform;
RefPtr<WebGLUniformLocationJS> mImageProgramTexMatrix;
RefPtr<WebGLUniformLocationJS> mImageProgramTexBounds;
RefPtr<WebGLUniformLocationJS> mImageProgramColor;
RefPtr<WebGLUniformLocationJS> mImageProgramSwizzle;
RefPtr<WebGLUniformLocationJS> mImageProgramSampler;
uint32_t mMaxTextureSize = 0;
CompositionOp mLastCompositionOp = CompositionOp::OP_SOURCE;
// A most-recently-used list of allocated texture handles.
LinkedList<RefPtr<TextureHandle>> mTextureHandles;
size_t mNumTextureHandles = 0;
// User data key linking a SourceSurface with its TextureHandle.
UserDataKey mTextureHandleKey = {0};
// User data key linking a SourceSurface with its shadow blur TextureHandle.
UserDataKey mShadowTextureKey = {0};
// User data key linking a ScaledFont with its GlyphCache.
UserDataKey mGlyphCacheKey = {0};
// List of all GlyphCaches currently allocated to fonts.
LinkedList<GlyphCache> mGlyphCaches;
// Cache of rasterized paths.
UniquePtr<PathCache> mPathCache;
// Collection of allocated shared texture pages that may be shared amongst
// many handles.
std::vector<RefPtr<SharedTexture>> mSharedTextures;
// Collection of allocated standalone textures that have a single assigned
// handle.
std::vector<RefPtr<StandaloneTexture>> mStandaloneTextures;
size_t mUsedTextureMemory = 0;
size_t mTotalTextureMemory = 0;
const Matrix& GetTransform() const { return mCurrentTarget->mTransform; }
bool IsContextLost() const;
bool Initialize();
bool CreateShaders();
void SetBlendState(CompositionOp aOp);
void SetClipRect(const IntRect& aClipRect) { mClipRect = aClipRect; }
bool IsCurrentTarget(DrawTargetWebgl* aDT) const {
return aDT == mCurrentTarget;
}
bool SetTarget(DrawTargetWebgl* aDT);
void ClearTarget() { mCurrentTarget = nullptr; }
void ClearLastTexture() { mLastTexture = nullptr; }
bool SupportsPattern(const Pattern& aPattern);
bool DrawRectAccel(const Rect& aRect, const Pattern& aPattern,
const DrawOptions& aOptions,
Maybe<DeviceColor> aMaskColor = Nothing(),
RefPtr<TextureHandle>* aHandle = nullptr,
bool aTransformed = true, bool aClipped = true,
bool aAccelOnly = false, bool aForceUpdate = false,
const StrokeOptions* aStrokeOptions = nullptr);
bool DrawPathAccel(const Path* aPath, const Pattern& aPattern,
const DrawOptions& aOptions,
const StrokeOptions* aStrokeOptions = nullptr);
bool DrawSurfaceWithShadowAccel(SourceSurface* aSurface, const Point& aDest,
const DeviceColor& aColor,
const Point& aOffset, Float aSigma,
CompositionOp aOperator);
bool FillGlyphsAccel(ScaledFont* aFont, const GlyphBuffer& aBuffer,
const Pattern& aPattern, const DrawOptions& aOptions);
void PruneTextureHandle(RefPtr<TextureHandle> aHandle);
bool PruneTextureMemory(size_t aMargin = 0, bool aPruneUnused = true);
bool RemoveSharedTexture(const RefPtr<SharedTexture>& aTexture);
bool RemoveStandaloneTexture(const RefPtr<StandaloneTexture>& aTexture);
void UnlinkSurfaceTextures();
void UnlinkSurfaceTexture(const RefPtr<TextureHandle>& aHandle);
void UnlinkGlyphCaches();
};
RefPtr<SharedContext> mSharedContext;
static WeakPtr<SharedContext> sSharedContext;
public:
DrawTargetWebgl();
@ -218,8 +318,16 @@ class DrawTargetWebgl : public DrawTarget {
}
private:
bool SupportsPattern(const Pattern& aPattern);
bool SupportsPattern(const Pattern& aPattern) {
return mSharedContext->SupportsPattern(aPattern);
}
bool PrepareContext(bool aClipped = true);
void DrawRectFallback(const Rect& aRect, const Pattern& aPattern,
const DrawOptions& aOptions,
Maybe<DeviceColor> aMaskColor, bool aTransform,
bool aClipped, const StrokeOptions* aStrokeOptions);
bool DrawRect(const Rect& aRect, const Pattern& aPattern,
const DrawOptions& aOptions,
Maybe<DeviceColor> aMaskColor = Nothing(),
@ -250,17 +358,7 @@ class DrawTargetWebgl : public DrawTarget {
bool ReadInto(uint8_t* aDstData, int32_t aDstStride);
bool CreateShaders();
bool RemoveSharedTexture(const RefPtr<SharedTexture>& aTexture);
bool RemoveStandaloneTexture(const RefPtr<StandaloneTexture>& aTexture);
void PruneTextureHandle(RefPtr<TextureHandle> aHandle);
bool PruneTextureMemory(size_t aMargin = 0, bool aPruneUnused = true);
void UnlinkSurfaceTextures();
void UnlinkSurfaceTexture(const RefPtr<TextureHandle>& aHandle);
void UnlinkGlyphCaches();
bool CreateFramebuffer();
};
} // namespace gfx

View File

@ -147,7 +147,7 @@ class TextureHandle : public RefCounted<TextureHandle>,
virtual void UpdateSize(const IntSize& aSize) {}
virtual void Cleanup(DrawTargetWebgl& aDT) {}
virtual void Cleanup(DrawTargetWebgl::SharedContext& aContext) {}
virtual ~TextureHandle() {}
@ -248,7 +248,7 @@ class SharedTextureHandle : public TextureHandle {
return TextureHandle::UsedBytes(GetFormat(), mBounds.Size());
}
void Cleanup(DrawTargetWebgl& aDT) override;
void Cleanup(DrawTargetWebgl::SharedContext& aContext) override;
const RefPtr<SharedTexture>& GetOwner() const { return mTexture; }
@ -284,7 +284,7 @@ class StandaloneTexture : public TextureHandle {
void UpdateSize(const IntSize& aSize) override { mSize = aSize; }
void Cleanup(DrawTargetWebgl& aDT) override;
void Cleanup(DrawTargetWebgl::SharedContext& aContext) override;
private:
IntSize mSize;

View File

@ -5061,12 +5061,12 @@
- name: gfx.canvas.accelerated.cache-items
type: RelaxedAtomicUint32
value: 1024
value: 2048
mirror: always
- name: gfx.canvas.accelerated.cache-size
type: RelaxedAtomicUint32
value: 128
value: 256
mirror: always
- name: gfx.canvas.accelerated.max-size