Bug 1936278 - Prevent search mode chiclet from being dismissed when clicking in page...
[gecko.git] / dom / canvas / DrawTargetWebglInternal.h
blob2e3af9230a7884f9cbd2fc479b7911e63722e814
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef _MOZILLA_GFX_DRAWTARGETWEBGL_INTERNAL_H
8 #define _MOZILLA_GFX_DRAWTARGETWEBGL_INTERNAL_H
10 #include "DrawTargetWebgl.h"
12 #include "mozilla/HashFunctions.h"
13 #include "mozilla/gfx/Etagere.h"
14 #include "mozilla/gfx/PathSkia.h"
15 #include "mozilla/gfx/WPFGpuRaster.h"
17 namespace mozilla::gfx {
19 // CacheEnty is a generic interface for various items that need to be cached to
20 // a texture.
21 class CacheEntry : public RefCounted<CacheEntry> {
22 public:
23 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(CacheEntry)
25 CacheEntry(const Matrix& aTransform, const IntRect& aBounds, HashNumber aHash)
26 : mTransform(aTransform), mBounds(aBounds), mHash(aHash) {}
27 virtual ~CacheEntry() = default;
29 void Link(const RefPtr<TextureHandle>& aHandle);
30 void Unlink();
32 const RefPtr<TextureHandle>& GetHandle() const { return mHandle; }
34 const Matrix& GetTransform() const { return mTransform; }
35 const IntRect& GetBounds() const { return mBounds; }
36 HashNumber GetHash() const { return mHash; }
38 virtual bool IsValid() const { return true; }
40 protected:
41 virtual void RemoveFromList() = 0;
43 // The handle of the rendered cache item.
44 RefPtr<TextureHandle> mHandle;
45 // The transform that was used to render the entry. This is necessary as
46 // the geometry might only be correctly rendered in device space after
47 // the transform is applied, so in general we can't cache untransformed
48 // geometry.
49 Matrix mTransform;
50 // The device space bounds of the rendered geometry.
51 IntRect mBounds;
52 // A hash of the geometry that may be used for quickly rejecting entries.
53 HashNumber mHash;
56 // CacheEntryImpl provides type-dependent boilerplate code for implementations
57 // of CacheEntry.
58 template <typename T>
59 class CacheEntryImpl : public CacheEntry, public LinkedListElement<RefPtr<T>> {
60 typedef LinkedListElement<RefPtr<T>> ListType;
62 public:
63 CacheEntryImpl(const Matrix& aTransform, const IntRect& aBounds,
64 HashNumber aHash)
65 : CacheEntry(aTransform, aBounds, aHash) {}
67 void RemoveFromList() override {
68 if (ListType::isInList()) {
69 ListType::remove();
74 // CacheImpl manages a list of CacheEntry.
75 template <typename T, bool BIG>
76 class CacheImpl {
77 protected:
78 typedef LinkedList<RefPtr<T>> ListType;
80 // Whether the cache should be small and space-efficient or prioritize speed.
81 static constexpr size_t kNumChains = BIG ? 499 : 71;
83 public:
84 ~CacheImpl() {
85 for (auto& chain : mChains) {
86 while (RefPtr<T> entry = chain.popLast()) {
87 entry->Unlink();
92 protected:
93 ListType& GetChain(HashNumber aHash) { return mChains[aHash % kNumChains]; }
95 void Insert(T* aEntry) { GetChain(aEntry->GetHash()).insertFront(aEntry); }
97 ListType mChains[kNumChains];
100 // BackingTexture provides information about the shared or standalone texture
101 // that is backing a texture handle.
102 class BackingTexture {
103 public:
104 BackingTexture(const IntSize& aSize, SurfaceFormat aFormat,
105 const RefPtr<WebGLTexture>& aTexture);
107 SurfaceFormat GetFormat() const { return mFormat; }
108 IntSize GetSize() const { return mSize; }
110 static inline size_t UsedBytes(SurfaceFormat aFormat, const IntSize& aSize) {
111 return size_t(BytesPerPixel(aFormat)) * size_t(aSize.width) *
112 size_t(aSize.height);
115 size_t UsedBytes() const { return UsedBytes(GetFormat(), GetSize()); }
117 const RefPtr<WebGLTexture>& GetWebGLTexture() const { return mTexture; }
119 bool IsInitialized() const { return mFlags & INITIALIZED; }
120 void MarkInitialized() { mFlags |= INITIALIZED; }
122 bool IsRenderable() const { return mFlags & RENDERABLE; }
123 void MarkRenderable() { mFlags |= RENDERABLE; }
125 protected:
126 IntSize mSize;
127 SurfaceFormat mFormat;
128 RefPtr<WebGLTexture> mTexture;
130 private:
131 enum Flags : uint8_t {
132 INITIALIZED = 1 << 0,
133 RENDERABLE = 1 << 1,
136 uint8_t mFlags = 0;
139 // TextureHandle is an abstract base class for supplying textures to drawing
140 // commands that may be backed by different resource types (such as a shared
141 // or standalone texture). It may be further linked to use-specific metadata
142 // such as for shadow drawing or for cached entries in the glyph cache.
143 class TextureHandle : public RefCounted<TextureHandle>,
144 public LinkedListElement<RefPtr<TextureHandle>> {
145 public:
146 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(TextureHandle)
148 enum Type { SHARED, STANDALONE };
150 virtual Type GetType() const = 0;
151 virtual IntRect GetBounds() const = 0;
152 IntSize GetSize() const { return GetBounds().Size(); }
153 virtual SurfaceFormat GetFormat() const = 0;
155 virtual BackingTexture* GetBackingTexture() = 0;
157 size_t UsedBytes() const {
158 return BackingTexture::UsedBytes(GetFormat(), GetSize());
161 virtual void UpdateSize(const IntSize& aSize) {}
163 virtual void Cleanup(SharedContextWebgl& aContext) {}
165 virtual ~TextureHandle() {}
167 bool IsValid() const { return mValid; }
168 void Invalidate() { mValid = false; }
170 void ClearSurface() { mSurface = nullptr; }
171 void SetSurface(const RefPtr<SourceSurface>& aSurface) {
172 mSurface = aSurface;
174 already_AddRefed<SourceSurface> GetSurface() const {
175 RefPtr<SourceSurface> surface(mSurface);
176 return surface.forget();
179 float GetSigma() const { return mSigma; }
180 void SetSigma(float aSigma) { mSigma = aSigma; }
181 bool IsShadow() const { return mSigma >= 0.0f; }
183 void SetSamplingOffset(const IntPoint& aSamplingOffset) {
184 mSamplingOffset = aSamplingOffset;
186 const IntPoint& GetSamplingOffset() const { return mSamplingOffset; }
187 IntRect GetSamplingRect() const {
188 return IntRect(GetSamplingOffset(), GetSize());
191 const RefPtr<CacheEntry>& GetCacheEntry() const { return mCacheEntry; }
192 void SetCacheEntry(const RefPtr<CacheEntry>& aEntry) { mCacheEntry = aEntry; }
194 // Note as used if there is corresponding surface or cache entry.
195 bool IsUsed() const {
196 return !mSurface.IsDead() || (mCacheEntry && mCacheEntry->IsValid());
199 private:
200 bool mValid = true;
201 // If applicable, weak pointer to the SourceSurface that is linked to this
202 // TextureHandle.
203 ThreadSafeWeakPtr<SourceSurface> mSurface;
204 // If this TextureHandle stores a cached shadow, then we need to remember the
205 // blur sigma used to produce the shadow.
206 float mSigma = -1.0f;
207 // If the originating surface requested a sampling rect, then we need to know
208 // the offset of the subrect within the surface for texture coordinates.
209 IntPoint mSamplingOffset;
210 // If applicable, the CacheEntry that is linked to this TextureHandle.
211 RefPtr<CacheEntry> mCacheEntry;
214 class SharedTextureHandle;
216 // SharedTexture is a large slab texture that is subdivided (by using a
217 // TexturePacker) to hold many small SharedTextureHandles. This avoids needing
218 // to allocate many WebGL textures for every single small Canvas 2D texture.
219 class SharedTexture : public RefCounted<SharedTexture>, public BackingTexture {
220 public:
221 MOZ_DECLARE_REFCOUNTED_TYPENAME(SharedTexture)
223 SharedTexture(const IntSize& aSize, SurfaceFormat aFormat,
224 const RefPtr<WebGLTexture>& aTexture);
225 ~SharedTexture();
227 already_AddRefed<SharedTextureHandle> Allocate(const IntSize& aSize);
228 bool Free(SharedTextureHandle& aHandle);
230 bool HasAllocatedHandles() const {
231 return mAtlasAllocator && Etagere::etagere_atlas_allocator_allocated_space(
232 mAtlasAllocator) > 0;
235 private:
236 Etagere::AtlasAllocator* mAtlasAllocator = nullptr;
239 // SharedTextureHandle is an allocated region within a large SharedTexture page
240 // that owns it.
241 class SharedTextureHandle : public TextureHandle {
242 friend class SharedTexture;
244 public:
245 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SharedTextureHandle, override)
247 SharedTextureHandle(Etagere::AllocationId aId, const IntRect& aBounds,
248 SharedTexture* aTexture);
250 Type GetType() const override { return Type::SHARED; }
252 IntRect GetBounds() const override { return mBounds; }
254 SurfaceFormat GetFormat() const override { return mTexture->GetFormat(); }
256 BackingTexture* GetBackingTexture() override { return mTexture.get(); }
258 void Cleanup(SharedContextWebgl& aContext) override;
260 const RefPtr<SharedTexture>& GetOwner() const { return mTexture; }
262 private:
263 Etagere::AllocationId mAllocationId = Etagere::INVALID_ALLOCATION_ID;
264 IntRect mBounds;
265 RefPtr<SharedTexture> mTexture;
268 // StandaloneTexture is a texture that can not be effectively shared within
269 // a SharedTexture page, such that it is better to assign it its own WebGL
270 // texture.
271 class StandaloneTexture : public TextureHandle, public BackingTexture {
272 public:
273 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(StandaloneTexture, override)
275 StandaloneTexture(const IntSize& aSize, SurfaceFormat aFormat,
276 const RefPtr<WebGLTexture>& aTexture);
278 Type GetType() const override { return Type::STANDALONE; }
280 IntRect GetBounds() const override {
281 return IntRect(IntPoint(0, 0), BackingTexture::GetSize());
284 SurfaceFormat GetFormat() const override {
285 return BackingTexture::GetFormat();
288 using BackingTexture::UsedBytes;
290 BackingTexture* GetBackingTexture() override { return this; }
292 void UpdateSize(const IntSize& aSize) override { mSize = aSize; }
294 void Cleanup(SharedContextWebgl& aContext) override;
297 // GlyphCacheEntry stores rendering metadata for a rendered text run, as well
298 // the handle to the texture it was rendered into, so that it can be located
299 // for reuse under similar rendering circumstances.
300 class GlyphCacheEntry : public CacheEntryImpl<GlyphCacheEntry> {
301 public:
302 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphCacheEntry, override)
304 GlyphCacheEntry(const GlyphBuffer& aBuffer, const DeviceColor& aColor,
305 const Matrix& aTransform, const IntPoint& aQuantizeScale,
306 const IntRect& aBounds, const IntRect& aFullBounds,
307 HashNumber aHash,
308 StoredStrokeOptions* aStrokeOptions = nullptr);
309 ~GlyphCacheEntry();
311 const GlyphBuffer& GetGlyphBuffer() const { return mBuffer; }
313 bool MatchesGlyphs(const GlyphBuffer& aBuffer, const DeviceColor& aColor,
314 const Matrix& aTransform, const IntPoint& aQuantizeOffset,
315 const IntPoint& aBoundsOffset, const IntRect& aClipRect,
316 HashNumber aHash, const StrokeOptions* aStrokeOptions);
318 static HashNumber HashGlyphs(const GlyphBuffer& aBuffer,
319 const Matrix& aTransform,
320 const IntPoint& aQuantizeScale);
322 private:
323 // The glyph keys used to render the text run.
324 GlyphBuffer mBuffer = {nullptr, 0};
325 // The color of the text run.
326 DeviceColor mColor;
327 // The full bounds of the text run without any clipping applied.
328 IntRect mFullBounds;
329 // Stroke options for the text run.
330 UniquePtr<StoredStrokeOptions> mStrokeOptions;
333 // GlyphCache maintains a list of GlyphCacheEntry's representing previously
334 // rendered text runs. The cache is searched to see if a given incoming text
335 // run has already been rendered to a texture, and if so, just reuses it.
336 // Otherwise, the text run will be rendered to a new texture handle and
337 // inserted into a new GlyphCacheEntry to represent it.
338 class GlyphCache : public LinkedListElement<GlyphCache>,
339 public CacheImpl<GlyphCacheEntry, false> {
340 public:
341 explicit GlyphCache(ScaledFont* aFont);
343 ScaledFont* GetFont() const { return mFont; }
345 already_AddRefed<GlyphCacheEntry> FindEntry(const GlyphBuffer& aBuffer,
346 const DeviceColor& aColor,
347 const Matrix& aTransform,
348 const IntPoint& aQuantizeScale,
349 const IntRect& aClipRect,
350 HashNumber aHash,
351 const StrokeOptions* aOptions);
353 already_AddRefed<GlyphCacheEntry> InsertEntry(
354 const GlyphBuffer& aBuffer, const DeviceColor& aColor,
355 const Matrix& aTransform, const IntPoint& aQuantizeScale,
356 const IntRect& aBounds, const IntRect& aFullBounds, HashNumber aHash,
357 const StrokeOptions* aOptions);
359 bool IsWhitespace(const GlyphBuffer& aBuffer) const;
360 void SetLastWhitespace(const GlyphBuffer& aBuffer);
362 private:
363 // Weak pointer to the owning font
364 ScaledFont* mFont;
365 // The last whitespace queried from this cache
366 Maybe<uint32_t> mLastWhitespace;
369 struct QuantizedPath {
370 explicit QuantizedPath(const WGR::Path& aPath);
371 // Ensure the path can only be moved, but not copied.
372 QuantizedPath(QuantizedPath&&) noexcept;
373 QuantizedPath(const QuantizedPath&) = delete;
374 ~QuantizedPath();
376 bool operator==(const QuantizedPath&) const;
378 WGR::Path mPath;
381 struct PathVertexRange {
382 uint32_t mOffset;
383 uint32_t mLength;
385 PathVertexRange() : mOffset(0), mLength(0) {}
386 PathVertexRange(uint32_t aOffset, uint32_t aLength)
387 : mOffset(aOffset), mLength(aLength) {}
389 bool IsValid() const { return mLength > 0; }
392 enum class AAStrokeMode {
393 Unsupported,
394 Geometry,
395 Mask,
398 // PathCacheEntry stores a rasterized version of a supplied path with a given
399 // pattern.
400 class PathCacheEntry : public CacheEntryImpl<PathCacheEntry> {
401 public:
402 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathCacheEntry, override)
404 PathCacheEntry(QuantizedPath&& aPath, Pattern* aPattern,
405 StoredStrokeOptions* aStrokeOptions, AAStrokeMode aStrokeMode,
406 const Matrix& aTransform, const IntRect& aBounds,
407 const Point& aOrigin, HashNumber aHash, float aSigma = -1.0f);
409 bool MatchesPath(const QuantizedPath& aPath, const Pattern* aPattern,
410 const StrokeOptions* aStrokeOptions,
411 AAStrokeMode aStrokeMode, const Matrix& aTransform,
412 const IntRect& aBounds, const Point& aOrigin,
413 HashNumber aHash, float aSigma);
415 static HashNumber HashPath(const QuantizedPath& aPath,
416 const Pattern* aPattern, const Matrix& aTransform,
417 const IntRect& aBounds, const Point& aOrigin);
419 const QuantizedPath& GetPath() const { return mPath; }
421 const Point& GetOrigin() const { return mOrigin; }
423 // Valid if either a mask (no pattern) or there is valid pattern.
424 bool IsValid() const override { return !mPattern || mPattern->IsValid(); }
426 const PathVertexRange& GetVertexRange() const { return mVertexRange; }
427 void SetVertexRange(const PathVertexRange& aRange) { mVertexRange = aRange; }
429 private:
430 // The actual path geometry supplied
431 QuantizedPath mPath;
432 // The transformed origin of the path
433 Point mOrigin;
434 // The pattern used to rasterize the path, if not a mask
435 UniquePtr<Pattern> mPattern;
436 // The StrokeOptions used for stroked paths, if applicable
437 UniquePtr<StoredStrokeOptions> mStrokeOptions;
438 // The AAStroke mode used for rendering a stroked path.
439 AAStrokeMode mAAStrokeMode = AAStrokeMode::Unsupported;
440 // The shadow blur sigma
441 float mSigma;
442 // If the path has cached geometry in the vertex buffer.
443 PathVertexRange mVertexRange;
446 class PathCache : public CacheImpl<PathCacheEntry, true> {
447 public:
448 PathCache() = default;
450 already_AddRefed<PathCacheEntry> FindOrInsertEntry(
451 QuantizedPath aPath, const Pattern* aPattern,
452 const StrokeOptions* aStrokeOptions, AAStrokeMode aStrokeMode,
453 const Matrix& aTransform, const IntRect& aBounds, const Point& aOrigin,
454 float aSigma = -1.0f);
456 void ClearVertexRanges();
459 } // namespace mozilla::gfx
461 #endif // _MOZILLA_GFX_DRAWTARGETWEBGL_INTERNAL_H