diff options
-rw-r--r-- | src/gpu/text/GrAtlasManager.cpp | 2 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasManager.h | 15 | ||||
-rw-r--r-- | src/gpu/text/GrGlyphCache.cpp | 34 | ||||
-rw-r--r-- | src/gpu/text/GrGlyphCache.h | 4 |
4 files changed, 50 insertions, 5 deletions
diff --git a/src/gpu/text/GrAtlasManager.cpp b/src/gpu/text/GrAtlasManager.cpp index ec07429180..e589b20814 100644 --- a/src/gpu/text/GrAtlasManager.cpp +++ b/src/gpu/text/GrAtlasManager.cpp @@ -7,10 +7,8 @@ #include "GrAtlasManager.h" -#include "GrCaps.h" #include "GrGlyph.h" #include "GrGlyphCache.h" -#include "GrProxyProvider.h" void GrAtlasManager::ComputeAtlasLimits(int maxTextureSize, size_t maxTextureBytes, int* maxDim, int* minDim, int* maxPlot, int* minPlot) { diff --git a/src/gpu/text/GrAtlasManager.h b/src/gpu/text/GrAtlasManager.h index 38e2781d4d..6c168534ad 100644 --- a/src/gpu/text/GrAtlasManager.h +++ b/src/gpu/text/GrAtlasManager.h @@ -8,8 +8,10 @@ #ifndef GrAtlasManager_DEFINED #define GrAtlasManager_DEFINED +#include "GrCaps.h" #include "GrDrawOpAtlas.h" #include "GrOnFlushResourceProvider.h" +#include "GrProxyProvider.h" class GrAtlasGlypCache; class GrTextStrike; @@ -28,11 +30,23 @@ public: float maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing); ~GrAtlasManager() override; + // Change an expected 565 mask format to 8888 if 565 is not supported (will happen when using + // Metal on macOS). The actual conversion of the data is handled in get_packed_glyph_image() in + // GrGlyphCache.cpp + GrMaskFormat resolveMaskFormat(GrMaskFormat format) const { + if (kA565_GrMaskFormat == format && + !fProxyProvider->caps()->isConfigTexturable(kRGB_565_GrPixelConfig)) { + format = kARGB_GrMaskFormat; + } + return format; + } + // if getProxies returns nullptr, the client must not try to use other functions on the // GrGlyphCache which use the atlas. This function *must* be called first, before other // functions which use the atlas. Note that we can have proxies available but none active // (i.e., none instantiated). const sk_sp<GrTextureProxy>* getProxies(GrMaskFormat format, unsigned int* numActiveProxies) { + format = this->resolveMaskFormat(format); if (this->initAtlas(format)) { *numActiveProxies = this->getAtlas(format)->numActivePages(); return this->getAtlas(format)->getProxies(); @@ -127,6 +141,7 @@ private: } GrDrawOpAtlas* getAtlas(GrMaskFormat format) const { + format = this->resolveMaskFormat(format); int atlasIndex = MaskFormatToAtlasIndex(format); SkASSERT(fAtlases[atlasIndex]); return fAtlases[atlasIndex].get(); diff --git a/src/gpu/text/GrGlyphCache.cpp b/src/gpu/text/GrGlyphCache.cpp index f6a18c3271..4890804fc0 100644 --- a/src/gpu/text/GrGlyphCache.cpp +++ b/src/gpu/text/GrGlyphCache.cpp @@ -8,13 +8,17 @@ #include "GrGlyphCache.h" #include "GrAtlasManager.h" #include "GrCaps.h" +#include "GrColor.h" #include "GrDistanceFieldGenFromVector.h" #include "SkAutoMalloc.h" #include "SkDistanceFieldGen.h" GrGlyphCache::GrGlyphCache(const GrCaps* caps, size_t maxTextureBytes) - : fPreserveStrike(nullptr), fGlyphSizeLimit(0) { + : fPreserveStrike(nullptr) + , fGlyphSizeLimit(0) + , f565Masks(SkMasks::CreateMasks({0xF800, 0x07E0, 0x001F, 0}, + GrMaskFormatBytesPerPixel(kA565_GrMaskFormat) * 8)) { fGlyphSizeLimit = ComputeGlyphSizeLimit(caps->maxTextureSize(), maxTextureBytes); } @@ -120,7 +124,7 @@ static void expand_bits(INT_TYPE* dst, static bool get_packed_glyph_image(SkGlyphCache* cache, const SkGlyph& glyph, int width, int height, int dstRB, GrMaskFormat expectedMaskFormat, - void* dst) { + void* dst, const SkMasks& masks) { SkASSERT(glyph.fWidth == width); SkASSERT(glyph.fHeight == height); const void* src = cache->findImage(glyph); @@ -128,6 +132,29 @@ static bool get_packed_glyph_image(SkGlyphCache* cache, const SkGlyph& glyph, in return false; } + // Convert if the glyph uses a 565 mask format since it is using LCD text rendering but the + // expected format is 8888 (will happen on macOS with Metal since that combination does not + // support 565). + if (kA565_GrMaskFormat == get_packed_glyph_mask_format(glyph) && + kARGB_GrMaskFormat == expectedMaskFormat) { + const int a565Bpp = GrMaskFormatBytesPerPixel(kA565_GrMaskFormat); + const int argbBpp = GrMaskFormatBytesPerPixel(kARGB_GrMaskFormat); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + uint16_t color565 = 0; + memcpy(&color565, src, a565Bpp); + uint32_t colorRGBA = GrColorPackRGBA(masks.getRed(color565), + masks.getGreen(color565), + masks.getBlue(color565), + 0xFF); + memcpy(dst, &colorRGBA, argbBpp); + src = (char*)src + a565Bpp; + dst = (char*)dst + argbBpp; + } + } + return true; + } + // crbug:510931 // Retrieving the image from the cache can actually change the mask format. This case is very // uncommon so for now we just draw a clear box for these glyphs. @@ -237,6 +264,7 @@ GrDrawOpAtlas::ErrorCode GrTextStrike::addGlyphToAtlas( SkASSERT(cache); SkASSERT(fCache.find(glyph->fPackedID)); + expectedMaskFormat = fullAtlasManager->resolveMaskFormat(expectedMaskFormat); int bytesPerPixel = GrMaskFormatBytesPerPixel(expectedMaskFormat); int width = glyph->width(); int height = glyph->height(); @@ -262,7 +290,7 @@ GrDrawOpAtlas::ErrorCode GrTextStrike::addGlyphToAtlas( } if (!get_packed_glyph_image(cache, skGlyph, glyph->width(), glyph->height(), rowBytes, expectedMaskFormat, - dataPtr)) { + dataPtr, glyphCache->getMasks())) { return GrDrawOpAtlas::ErrorCode::kError; } diff --git a/src/gpu/text/GrGlyphCache.h b/src/gpu/text/GrGlyphCache.h index 7e707ec64c..8375d1f19a 100644 --- a/src/gpu/text/GrGlyphCache.h +++ b/src/gpu/text/GrGlyphCache.h @@ -12,6 +12,7 @@ #include "GrGlyph.h" #include "SkArenaAlloc.h" #include "SkGlyphCache.h" +#include "SkMasks.h" #include "SkTDynamicHash.h" class GrGlyphCache; @@ -127,6 +128,8 @@ public: return strike; } + const SkMasks& getMasks() const { return *f565Masks; } + void freeAll(); static void HandleEviction(GrDrawOpAtlas::AtlasID, void*); @@ -145,6 +148,7 @@ private: StrikeHash fCache; GrTextStrike* fPreserveStrike; SkScalar fGlyphSizeLimit; + std::unique_ptr<const SkMasks> f565Masks; }; #endif |