Bug 1348980 - use UnscaledFont to track WebRender font keys. r=jrmuizel

This commit is contained in:
Lee Salzman 2017-04-06 17:41:24 -04:00
Родитель a168dcdbf3
Коммит 22fb7629b8
14 изменённых файлов: 172 добавлений и 112 удалений

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

@ -46,6 +46,7 @@ parent:
SurfaceFormat aFormat, ByteBuffer aBytes);
sync DeleteImage(ImageKey aImageKey);
async AddRawFont(FontKey aFontKey, ByteBuffer aBytes, uint32_t aFontIndex);
async DeleteFont(FontKey aFontKey);
async DPBegin(IntSize aSize);
async DPEnd(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
ByteBuffer aDL, WrBuiltDisplayListDescriptor aDLDesc, ByteBuffer aAux, WrAuxiliaryListsDescriptor aAuxDesc);

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

@ -24,6 +24,7 @@ WebRenderBridgeChild::WebRenderBridgeChild(const wr::PipelineId& aPipelineId)
, mPipelineId(aPipelineId)
, mIPCOpen(false)
, mDestroyed(false)
, mFontKeysDeleted(0)
{
}
@ -151,6 +152,112 @@ WebRenderBridgeChild::DeallocExternalImageId(uint64_t aImageId)
SendRemoveExternalImageId(aImageId);
}
struct FontFileData
{
wr::ByteBuffer mFontBuffer;
uint32_t mFontIndex;
float mGlyphSize;
};
static void
WriteFontFileData(const uint8_t* aData, uint32_t aLength, uint32_t aIndex,
float aGlyphSize, uint32_t aVariationCount,
const ScaledFont::VariationSetting* aVariations, void* aBaton)
{
FontFileData* data = static_cast<FontFileData*>(aBaton);
if (!data->mFontBuffer.Allocate(aLength)) {
return;
}
memcpy(data->mFontBuffer.mData, aData, aLength);
data->mFontIndex = aIndex;
data->mGlyphSize = aGlyphSize;
}
void
WebRenderBridgeChild::PushGlyphs(wr::DisplayListBuilder& aBuilder, const nsTArray<GlyphArray>& aGlyphs,
gfx::ScaledFont* aFont, const gfx::Point& aOffset, const gfx::Rect& aBounds,
const gfx::Rect& aClip)
{
MOZ_ASSERT(aFont);
MOZ_ASSERT(!aGlyphs.IsEmpty());
WrFontKey key = GetFontKeyForScaledFont(aFont);
MOZ_ASSERT(key.mNamespace && key.mHandle);
WrClipRegion clipRegion = aBuilder.BuildClipRegion(wr::ToWrRect(aClip));
for (size_t i = 0; i < aGlyphs.Length(); i++) {
GlyphArray glyph_array = aGlyphs[i];
nsTArray<gfx::Glyph>& glyphs = glyph_array.glyphs();
nsTArray<WrGlyphInstance> wr_glyph_instances;
wr_glyph_instances.SetLength(glyphs.Length());
for (size_t j = 0; j < glyphs.Length(); j++) {
wr_glyph_instances[j].index = glyphs[j].mIndex;
wr_glyph_instances[j].x = glyphs[j].mPosition.x - aOffset.x;
wr_glyph_instances[j].y = glyphs[j].mPosition.y - aOffset.y;
}
aBuilder.PushText(wr::ToWrRect(aBounds),
clipRegion,
glyph_array.color().value(),
key,
Range<const WrGlyphInstance>(wr_glyph_instances.Elements(), wr_glyph_instances.Length()),
aFont->GetSize());
}
}
wr::FontKey
WebRenderBridgeChild::GetFontKeyForScaledFont(gfx::ScaledFont* aScaledFont)
{
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(aScaledFont);
MOZ_ASSERT((aScaledFont->GetType() == gfx::FontType::DWRITE) ||
(aScaledFont->GetType() == gfx::FontType::MAC) ||
(aScaledFont->GetType() == gfx::FontType::FONTCONFIG));
RefPtr<UnscaledFont> unscaled = aScaledFont->GetUnscaledFont();
MOZ_ASSERT(unscaled);
wr::FontKey key = {0, 0};
if (mFontKeys.Get(unscaled, &key)) {
return key;
}
FontFileData data;
if (!aScaledFont->GetFontFileData(WriteFontFileData, &data) ||
!data.mFontBuffer.mData) {
return key;
}
key.mNamespace = GetNamespace();
key.mHandle = GetNextResourceId();
SendAddRawFont(key, data.mFontBuffer, data.mFontIndex);
mFontKeys.Put(unscaled, key);
return key;
}
void
WebRenderBridgeChild::RemoveExpiredFontKeys()
{
uint32_t counter = UnscaledFont::DeletionCounter();
if (mFontKeysDeleted != counter) {
mFontKeysDeleted = counter;
for (auto iter = mFontKeys.Iter(); !iter.Done(); iter.Next()) {
if (!iter.Key()) {
SendDeleteFont(iter.Data());
iter.Remove();
}
}
}
}
CompositorBridgeChild*
WebRenderBridgeChild::GetCompositorBridgeChild()
{

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

@ -26,6 +26,28 @@ class CompositableClient;
class CompositorBridgeChild;
class TextureForwarder;
class UnscaledFontHashKey : public PLDHashEntryHdr
{
public:
typedef gfx::UnscaledFont* KeyType;
typedef const gfx::UnscaledFont* KeyTypePointer;
explicit UnscaledFontHashKey(KeyTypePointer aKey) : mKey(const_cast<KeyType>(aKey)) {}
KeyType GetKey() const { return mKey; }
bool KeyEquals(KeyTypePointer aKey) const { return aKey == mKey; }
static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey)
{
return NS_PTR_TO_UINT32(aKey) >> 2;
}
enum { ALLOW_MEMMOVE = true };
private:
WeakPtr<gfx::UnscaledFont> mKey;
};
class WebRenderBridgeChild final : public PWebRenderBridgeChild
, public CompositableForwarder
{
@ -67,6 +89,14 @@ public:
mIdNamespace = aIdNamespace;
}
void PushGlyphs(wr::DisplayListBuilder& aBuilder, const nsTArray<GlyphArray>& aGlyphs,
gfx::ScaledFont* aFont, const gfx::Point& aOffset, const gfx::Rect& aBounds,
const gfx::Rect& aClip);
wr::FontKey GetFontKeyForScaledFont(gfx::ScaledFont* aScaledFont);
void RemoveExpiredFontKeys();
private:
friend class CompositorBridgeChild;
@ -123,6 +153,9 @@ private:
bool mIPCOpen;
bool mDestroyed;
uint32_t mFontKeysDeleted;
nsDataHashtable<UnscaledFontHashKey, wr::FontKey> mFontKeys;
};
} // namespace layers

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

@ -226,7 +226,16 @@ WebRenderBridgeParent::RecvAddRawFont(const wr::FontKey& aFontKey,
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvDeleteFont(const wr::FontKey& aFontKey)
{
if (mDestroyed) {
return IPC_OK();
}
MOZ_ASSERT(mApi);
mApi->DeleteFont(aFontKey);
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvUpdateImage(const wr::ImageKey& aImageKey,

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

@ -73,14 +73,15 @@ public:
const uint32_t& aStride,
const gfx::SurfaceFormat& aFormat,
const ByteBuffer& aBuffer) override;
mozilla::ipc::IPCResult RecvAddRawFont(const wr::FontKey& aFontKey,
const ByteBuffer& aBuffer,
const uint32_t& aFontIndex) override;
mozilla::ipc::IPCResult RecvUpdateImage(const wr::ImageKey& aImageKey,
const gfx::IntSize& aSize,
const gfx::SurfaceFormat& aFormat,
const ByteBuffer& aBuffer) override;
mozilla::ipc::IPCResult RecvDeleteImage(const wr::ImageKey& a1) override;
mozilla::ipc::IPCResult RecvAddRawFont(const wr::FontKey& aFontKey,
const ByteBuffer& aBuffer,
const uint32_t& aFontIndex) override;
mozilla::ipc::IPCResult RecvDeleteFont(const wr::FontKey& aFontKey) override;
mozilla::ipc::IPCResult RecvDPBegin(const gfx::IntSize& aSize) override;
mozilla::ipc::IPCResult RecvDPEnd(const gfx::IntSize& aSize,
InfallibleTArray<WebRenderParentCommand>&& aCommands,

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

@ -288,6 +288,7 @@ WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
EndTransactionFlags aFlags)
{
DiscardImages();
WrBridge()->RemoveExpiredFontKeys();
mPaintedLayerCallback = aCallback;
mPaintedLayerCallbackData = aCallbackData;

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

@ -39,8 +39,7 @@ WebRenderTextLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
Stringify(clip).c_str());
}
mGlyphHelper.BuildWebRenderCommands(WrBridge(), aBuilder, mGlyphs, mFont,
GetOffsetToParent(), rect, clip);
WrBridge()->PushGlyphs(aBuilder, mGlyphs, mFont, GetOffsetToParent(), rect, clip);
}
} // namespace layers

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

@ -33,8 +33,6 @@ public:
Layer* GetLayer() override { return this; }
void RenderLayer(wr::DisplayListBuilder& aBuilder) override;
protected:
gfx::WebRenderGlyphHelper mGlyphHelper;
};
} // namespace layers

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

@ -21,14 +21,10 @@
#include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/gfx/Swizzle.h"
#include "mozilla/layers/WebRenderMessages.h"
#include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtrExtensions.h"
#include "mozilla/Vector.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "nsComponentManagerUtils.h"
#include "nsIClipboardHelper.h"
#include "nsIFile.h"
@ -1443,68 +1439,5 @@ Color ToDeviceColor(nscolor aColor)
return ToDeviceColor(Color::FromABGR(aColor));
}
static void
WriteFontFileData(const uint8_t* aData, uint32_t aLength, uint32_t aIndex,
float aGlyphSize, uint32_t aVariationCount,
const ScaledFont::VariationSetting* aVariations, void* aBaton)
{
WebRenderGlyphHelper* helper = static_cast<WebRenderGlyphHelper*>(aBaton);
uint8_t* fontData = (uint8_t*)malloc(aLength * sizeof(uint8_t));
memcpy(fontData, aData, aLength * sizeof(uint8_t));
helper->mFontData = fontData;
helper->mFontDataLength = aLength;
helper->mIndex = aIndex;
helper->mGlyphSize = aGlyphSize;
}
void
WebRenderGlyphHelper::BuildWebRenderCommands(WebRenderBridgeChild* aBridge,
wr::DisplayListBuilder& aBuilder,
const nsTArray<GlyphArray>& aGlyphs,
ScaledFont* aFont,
const Point& aOffset,
const Rect& aBounds,
const Rect& aClip)
{
MOZ_ASSERT(aFont);
MOZ_ASSERT(!aGlyphs.IsEmpty());
MOZ_ASSERT((aFont->GetType() == gfx::FontType::DWRITE) ||
(aFont->GetType() == gfx::FontType::MAC));
aFont->GetFontFileData(&WriteFontFileData, this);
wr::ByteBuffer fontBuffer(mFontDataLength, mFontData);
WrFontKey key;
key.mNamespace = aBridge->GetNamespace();
key.mHandle = aBridge->GetNextResourceId();
aBridge->SendAddRawFont(key, fontBuffer, mIndex);
WrClipRegion clipRegion = aBuilder.BuildClipRegion(wr::ToWrRect(aClip));
for (size_t i = 0; i < aGlyphs.Length(); i++) {
GlyphArray glyph_array = aGlyphs[i];
nsTArray<gfx::Glyph>& glyphs = glyph_array.glyphs();
nsTArray<WrGlyphInstance> wr_glyph_instances;
wr_glyph_instances.SetLength(glyphs.Length());
for (size_t j = 0; j < glyphs.Length(); j++) {
wr_glyph_instances[j].index = glyphs[j].mIndex;
wr_glyph_instances[j].x = glyphs[j].mPosition.x - aOffset.x;
wr_glyph_instances[j].y = glyphs[j].mPosition.y - aOffset.y;
}
aBuilder.PushText(wr::ToWrRect(aBounds),
clipRegion,
glyph_array.color().value(),
key,
Range<const WrGlyphInstance>(wr_glyph_instances.Elements(), wr_glyph_instances.Length()),
mGlyphSize);
}
}
} // namespace gfx
} // namespace mozilla

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

@ -17,7 +17,7 @@
#include "nsRegionFwd.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/webrender/webrender_ffi.h"
#include "mozilla/webrender/WebRenderTypes.h"
class gfxASurface;
class gfxDrawable;
@ -313,38 +313,6 @@ SafeBytesForBitmap(uint32_t aWidth, uint32_t aHeight, unsigned aBytesPerPixel)
return width * height * aBytesPerPixel;
}
class WebRenderGlyphHelper final {
public:
WebRenderGlyphHelper()
: mFontData(nullptr)
, mFontDataLength(0)
, mIndex(0)
, mGlyphSize(0.0)
{
}
~WebRenderGlyphHelper()
{
if (mFontData) {
free(mFontData);
}
}
void BuildWebRenderCommands(layers::WebRenderBridgeChild* aChild,
wr::DisplayListBuilder& aBuilder,
const nsTArray<layers::GlyphArray>& aGlyphs,
ScaledFont* aFont,
const Point& aOffset,
const Rect& aBounds,
const Rect& aClip);
public:
uint8_t* mFontData;
uint32_t mFontDataLength;
uint32_t mIndex;
float mGlyphSize;
};
} // namespace gfx
} // namespace mozilla

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

@ -445,7 +445,7 @@ WebRenderAPI::AddRawFont(wr::FontKey key, Range<uint8_t> aBytes)
void
WebRenderAPI::DeleteFont(wr::FontKey aKey)
{
printf("XXX - WebRender does not seem to implement deleting a font! Leaking it...\n");
wr_api_delete_font(mWrApi, aKey);
}
class EnableProfiler : public RendererEvent

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

@ -941,6 +941,13 @@ pub extern "C" fn wr_api_add_raw_font(api: &mut RenderApi,
api.add_raw_font(key, font_vector);
}
#[no_mangle]
pub extern "C" fn wr_api_delete_font(api: &mut RenderApi, key: FontKey)
{
assert!( unsafe { is_in_compositor_thread() });
api.delete_font(key);
}
#[no_mangle]
pub unsafe extern "C" fn wr_api_get_namespace(api: &mut RenderApi) -> IdNamespace {
api.id_namespace

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

@ -601,6 +601,10 @@ WR_INLINE void
wr_api_add_raw_font(WrAPI* api, WrFontKey key, uint8_t* font_buffer, size_t buffer_size)
WR_FUNC;
WR_INLINE void
wr_api_delete_font(WrAPI* api, WrFontKey key)
WR_FUNC;
WR_INLINE WrIdNamespace
wr_api_get_namespace(WrAPI* api)
WR_FUNC;

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

@ -309,7 +309,6 @@ private:
nsPoint mPoint;
RefPtr<ScaledFont> mFont;
nsTArray<layers::GlyphArray> mGlyphs;
WebRenderGlyphHelper mGlyphHelper;
// Store the type of list-style-type.
int32_t mListStyleType;
@ -506,8 +505,8 @@ BulletRenderer::CreateWebRenderCommandsForText(nsDisplayItem* aItem,
NSRectToRect(aItem->GetBounds(builder, &dummy), appUnitsPerDevPixel);
Rect destRectTransformed = aLayer->RelativeToParent(destRect);
mGlyphHelper.BuildWebRenderCommands(layer->WrBridge(), aBuilder, mGlyphs, mFont, aLayer->GetOffsetToParent(),
destRectTransformed, destRectTransformed);
layer->WrBridge()->PushGlyphs(aBuilder, mGlyphs, mFont, aLayer->GetOffsetToParent(),
destRectTransformed, destRectTransformed);
}
class nsDisplayBullet final : public nsDisplayItem {