mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1329314 - Add support for nsDisplayText webrender display item. r=jrmuizel?
This commit is contained in:
parent
80b721469e
commit
5e1c34af71
27
README.displayitem
Normal file
27
README.displayitem
Normal file
@ -0,0 +1,27 @@
|
||||
How to add a new WebRender display item from a Gecko Display item, the general flow is to:
|
||||
|
||||
(1) Force layout to create a new active layer for the gecko display item.
|
||||
(2) Plumb the data needed for the display item from content through WebRenderBridgeParent on the parent side.
|
||||
(3) From WebRenderBridgeParent, call out into bindings.rs and implement the appropriate WR calls.
|
||||
|
||||
More detailed steps are:
|
||||
|
||||
1) Force layout to create an active layer for the gecko display item.
|
||||
See http://searchfox.org/mozilla-central/rev/0f254a30d684796bcc8b6e2a102a0095d25842bb/layout/generic/nsTextFrame.cpp#4983
|
||||
as an example for text layers. Ping Matt Woodrow or Markus Stange for help.
|
||||
|
||||
The Active layer part comes from nsDisplayText::GetLayerState
|
||||
|
||||
2) Create the new display item layer:
|
||||
|
||||
See text layer:
|
||||
http://searchfox.org/mozilla-central/rev/0f254a30d684796bcc8b6e2a102a0095d25842bb/gfx/layers/Layers.h#2403
|
||||
|
||||
The layer should have all the information to display the item.
|
||||
|
||||
3) Create the WebRender equivalent layer. In YourLayerType::RenderLayer, serialize the data needed for the layer type.
|
||||
4) If you need to add a custom IPC serialization mechanism, do it in WebRenderTypes.h
|
||||
5) Create a WebRender command to process the new layer type in WebRenderMessages.ipdlh. These are the struct OpDPPushYourLayerTypeHere
|
||||
6) Add a new function in WebRender.h that will call out into webrender to render your display item.
|
||||
7) In WebRenderBridgeParent::ProcessWebRenderCommands, call out to the new function in (6).
|
||||
8) Fill out the function in (6) in bindings.rs to make webrender do the right thing. Generally, it's just push a display item.
|
@ -716,6 +716,8 @@ public:
|
||||
|
||||
virtual bool GetFontDescriptor(FontDescriptorOutput, void *) { return false; }
|
||||
|
||||
virtual bool CanSerialize() { return false; }
|
||||
|
||||
void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) {
|
||||
mUserData.Add(key, userData, destroy);
|
||||
}
|
||||
|
@ -228,6 +228,10 @@ ScaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aDataCallback) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<IDWriteFontFile> file;
|
||||
mFontFace->GetFiles(&fileCount, getter_AddRefs(file));
|
||||
|
||||
|
@ -40,6 +40,8 @@ public:
|
||||
|
||||
virtual bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton);
|
||||
|
||||
virtual bool CanSerialize() override { return true; }
|
||||
|
||||
virtual AntialiasMode GetDefaultAAMode() override;
|
||||
|
||||
bool UseEmbeddedBitmaps() { return mUseEmbeddedBitmap; }
|
||||
|
@ -15,8 +15,10 @@ using WRColor from "mozilla/gfx/webrender.h";
|
||||
using WRImageKey from "mozilla/gfx/webrender.h";
|
||||
using WRLayoutSize from "mozilla/gfx/webrender.h";
|
||||
using WRRect from "mozilla/gfx/webrender.h";
|
||||
using WRGlyphArray from "mozilla/gfx/webrender.h";
|
||||
using MaybeImageMask from "mozilla/layers/WebRenderTypes.h";
|
||||
using mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h";
|
||||
using mozilla::gfx::ByteBuffer from "mozilla/layers/WebRenderTypes.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
@ -72,6 +74,16 @@ struct OpDPPushIframe {
|
||||
uint64_t layersid;
|
||||
};
|
||||
|
||||
struct OpDPPushText {
|
||||
WRRect bounds;
|
||||
WRRect clip;
|
||||
WRGlyphArray[] glyph_array;
|
||||
uint32_t font_index;
|
||||
float glyph_size;
|
||||
ByteBuffer font_buffer;
|
||||
uint32_t font_buffer_length;
|
||||
};
|
||||
|
||||
union WebRenderCommand {
|
||||
OpDPPushStackingContext;
|
||||
OpDPPopStackingContext;
|
||||
@ -80,6 +92,7 @@ union WebRenderCommand {
|
||||
OpDPPushImage;
|
||||
OpDPPushExternalImageId;
|
||||
OpDPPushIframe;
|
||||
OpDPPushText;
|
||||
CompositableOperation;
|
||||
};
|
||||
|
||||
|
@ -384,6 +384,7 @@ UNIFIED_SOURCES += [
|
||||
'wr/WebRenderImageLayer.cpp',
|
||||
'wr/WebRenderLayerManager.cpp',
|
||||
'wr/WebRenderPaintedLayer.cpp',
|
||||
'wr/WebRenderTextLayer.cpp',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
|
@ -323,6 +323,27 @@ WebRenderBridgeParent::ProcessWebrenderCommands(InfallibleTArray<WebRenderComman
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WebRenderCommand::TOpDPPushText: {
|
||||
const OpDPPushText& op = cmd.get_OpDPPushText();
|
||||
const nsTArray<WRGlyphArray>& glyph_array = op.glyph_array();
|
||||
|
||||
for (size_t i = 0; i < glyph_array.Length(); i++) {
|
||||
const nsTArray<WRGlyphInstance>& glyphs = glyph_array[i].glyphs;
|
||||
|
||||
wr_dp_push_text(mWRWindowState,
|
||||
mWRState,
|
||||
op.bounds(),
|
||||
op.clip(),
|
||||
glyph_array[i].color,
|
||||
glyphs.Elements(),
|
||||
glyphs.Length(),
|
||||
op.glyph_size(),
|
||||
op.font_buffer().mData,
|
||||
op.font_buffer_length());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_RUNTIMEABORT("not reached");
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "WebRenderContainerLayer.h"
|
||||
#include "WebRenderImageLayer.h"
|
||||
#include "WebRenderPaintedLayer.h"
|
||||
#include "WebRenderTextLayer.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -472,7 +473,7 @@ WebRenderLayerManager::CreateRefLayer()
|
||||
already_AddRefed<TextLayer>
|
||||
WebRenderLayerManager::CreateTextLayer()
|
||||
{
|
||||
return nullptr;
|
||||
return MakeAndAddRef<WebRenderTextLayer>(this);
|
||||
}
|
||||
|
||||
already_AddRefed<BorderLayer>
|
||||
|
77
gfx/layers/wr/WebRenderTextLayer.cpp
Normal file
77
gfx/layers/wr/WebRenderTextLayer.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebRenderTextLayer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
static void
|
||||
DWriteFontFileData(const uint8_t* aData, uint32_t aLength, uint32_t aIndex,
|
||||
float aGlyphSize, void* aBaton)
|
||||
{
|
||||
WebRenderTextLayer* layer = static_cast<WebRenderTextLayer*>(aBaton);
|
||||
|
||||
uint8_t* fontData = (uint8_t*)malloc(aLength * sizeof(uint8_t));
|
||||
memcpy(fontData, aData, aLength * sizeof(uint8_t));
|
||||
|
||||
layer->mFontData = fontData;
|
||||
layer->mFontDataLength = aLength;
|
||||
layer->mIndex = aIndex;
|
||||
layer->mGlyphSize = aGlyphSize;
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderTextLayer::RenderLayer()
|
||||
{
|
||||
if (mBounds.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
gfx::Rect rect = RelativeToParent(GetTransform().TransformBounds(IntRectToRect(mBounds)));
|
||||
gfx::Rect clip;
|
||||
if (GetClipRect().isSome()) {
|
||||
clip = RelativeToParent(IntRectToRect(GetClipRect().ref().ToUnknownRect()));
|
||||
} else {
|
||||
clip = rect;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mFont->GetType() == FontType::DWRITE);
|
||||
mFont->GetFontFileData(&DWriteFontFileData, this);
|
||||
gfx::ByteBuffer fontBuffer(mFontDataLength, mFontData);
|
||||
|
||||
nsTArray<WRGlyphArray> wr_glyphs;
|
||||
wr_glyphs.SetLength(mGlyphs.Length());
|
||||
|
||||
for (size_t i = 0; i < mGlyphs.Length(); i++) {
|
||||
GlyphArray glyph_array = mGlyphs[i];
|
||||
nsTArray<Glyph>& glyphs = glyph_array.glyphs();
|
||||
|
||||
nsTArray<WRGlyphInstance>& wr_glyph_instances = wr_glyphs[i].glyphs;
|
||||
wr_glyph_instances.SetLength(glyphs.Length());
|
||||
wr_glyphs[i].color = toWrColor(glyph_array.color().value());
|
||||
|
||||
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;
|
||||
wr_glyph_instances[j].y = glyphs[j].mPosition.y;
|
||||
}
|
||||
}
|
||||
|
||||
WRBridge()->AddWebRenderCommand(OpDPPushText(
|
||||
toWrRect(rect),
|
||||
toWrRect(clip),
|
||||
wr_glyphs,
|
||||
mIndex,
|
||||
mGlyphSize,
|
||||
fontBuffer,
|
||||
mFontDataLength
|
||||
));
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
51
gfx/layers/wr/WebRenderTextLayer.h
Normal file
51
gfx/layers/wr/WebRenderTextLayer.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#ifndef GFX_WEBRENDERTEXTLAYER_H
|
||||
#define GFX_WEBRENDERTEXTLAYER_H
|
||||
|
||||
#include "Layers.h"
|
||||
#include "WebRenderLayerManager.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class WebRenderTextLayer : public WebRenderLayer,
|
||||
public TextLayer {
|
||||
public:
|
||||
explicit WebRenderTextLayer(WebRenderLayerManager* aLayerManager)
|
||||
: TextLayer(aLayerManager, static_cast<WebRenderLayer*>(this))
|
||||
, mFontData(nullptr)
|
||||
, mFontDataLength(0)
|
||||
, mIndex(0)
|
||||
, mGlyphSize(0.0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(WebRenderTextLayer);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~WebRenderTextLayer()
|
||||
{
|
||||
MOZ_COUNT_DTOR(WebRenderTextLayer);
|
||||
if (mFontData) {
|
||||
free(mFontData);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
Layer* GetLayer() override { return this; }
|
||||
void RenderLayer() override;
|
||||
|
||||
uint8_t* mFontData;
|
||||
uint32_t mFontDataLength;
|
||||
uint32_t mIndex;
|
||||
float mGlyphSize;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GFX_WEBRENDERTEXTLAYER_H
|
@ -49,6 +49,11 @@ struct ByteBuffer
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const ByteBuffer& other) const {
|
||||
return mLength == other.mLength &&
|
||||
!(memcmp(mData, other.mData, mLength));
|
||||
}
|
||||
|
||||
size_t mLength;
|
||||
uint8_t* mData;
|
||||
bool mOwned;
|
||||
@ -139,6 +144,66 @@ struct ParamTraits<WRColor>
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WRGlyphInstance>
|
||||
{
|
||||
static void
|
||||
Write(Message* aMsg, const WRGlyphInstance& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.index);
|
||||
WriteParam(aMsg, aParam.x);
|
||||
WriteParam(aMsg, aParam.y);
|
||||
}
|
||||
|
||||
static bool
|
||||
Read(const Message* aMsg, PickleIterator* aIter, WRGlyphInstance* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->index)
|
||||
&& ReadParam(aMsg, aIter, &aResult->x)
|
||||
&& ReadParam(aMsg, aIter, &aResult->y);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WRGlyphArray>
|
||||
{
|
||||
static void
|
||||
Write(Message* aMsg, const WRGlyphArray& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.color);
|
||||
size_t length = aParam.glyphs.Length();
|
||||
|
||||
WriteParam(aMsg, length);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
WriteParam(aMsg, aParam.glyphs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
Read(const Message* aMsg, PickleIterator* aIter, WRGlyphArray* aResult)
|
||||
{
|
||||
if (!ReadParam(aMsg, aIter, &aResult->color)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t length;
|
||||
if (!ReadParam(aMsg, aIter, &length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResult->glyphs.SetLength(length);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
if (!ReadParam(aMsg, aIter, &aResult->glyphs[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<WRBorderSide>
|
||||
{
|
||||
|
@ -7,7 +7,7 @@ use std::os::raw::{c_void, c_char};
|
||||
use gleam::gl;
|
||||
use webrender_traits::{BorderSide, BorderStyle, BorderRadius};
|
||||
use webrender_traits::{PipelineId, ClipRegion};
|
||||
use webrender_traits::{Epoch, ColorF};
|
||||
use webrender_traits::{Epoch, ColorF, GlyphInstance};
|
||||
use webrender_traits::{ImageData, ImageFormat, ImageKey, ImageMask, ImageRendering, RendererKind};
|
||||
use webrender_traits::{ExternalImageId};
|
||||
use webrender_traits::{DeviceUintSize};
|
||||
@ -15,6 +15,8 @@ use webrender_traits::{LayoutPoint, LayoutRect, LayoutSize, LayoutTransform};
|
||||
use webrender::renderer::{Renderer, RendererOptions};
|
||||
use webrender::renderer::{ExternalImage, ExternalImageHandler, ExternalImageSource};
|
||||
use std::sync::{Arc, Mutex, Condvar};
|
||||
use app_units::Au;
|
||||
|
||||
extern crate webrender_traits;
|
||||
|
||||
fn get_proc_address(glcontext_ptr: *mut c_void, name: &str) -> *const c_void{
|
||||
@ -573,3 +575,43 @@ pub extern fn wr_profiler_set_enabled(window: &mut WrWindowState, enabled: bool)
|
||||
assert!( unsafe { is_in_compositor_thread() });
|
||||
window.renderer.set_profiler_enabled(enabled);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn wr_dp_push_text(window: &mut WrWindowState,
|
||||
state: &mut WrState,
|
||||
bounds: WrRect,
|
||||
clip: WrRect,
|
||||
color: WrColor,
|
||||
glyphs: *mut GlyphInstance,
|
||||
glyph_count: u32,
|
||||
glyph_size: f32,
|
||||
font_buffer: *mut u8,
|
||||
buffer_size: usize)
|
||||
{
|
||||
assert!( unsafe { is_in_compositor_thread() });
|
||||
|
||||
let font_slice = unsafe {
|
||||
slice::from_raw_parts(font_buffer, buffer_size as usize)
|
||||
};
|
||||
let mut font_vector = Vec::new();
|
||||
font_vector.extend_from_slice(font_slice);
|
||||
let font_key = window.api.add_raw_font(font_vector);
|
||||
|
||||
let glyph_slice = unsafe {
|
||||
slice::from_raw_parts(glyphs, glyph_count as usize)
|
||||
};
|
||||
let mut glyph_vector = Vec::new();
|
||||
glyph_vector.extend_from_slice(&glyph_slice);
|
||||
|
||||
let colorf = ColorF::new(color.r, color.g, color.b, color.a);
|
||||
|
||||
let clip_region = state.frame_builder.dl_builder.new_clip_region(&clip.to_rect(), Vec::new(), None);
|
||||
|
||||
state.frame_builder.dl_builder.push_text(bounds.to_rect(),
|
||||
clip_region,
|
||||
glyph_vector,
|
||||
font_key,
|
||||
colorf,
|
||||
Au::from_f32_px(glyph_size),
|
||||
Au::from_px(0));
|
||||
}
|
@ -6,6 +6,9 @@
|
||||
|
||||
#ifndef WR_h
|
||||
#define WR_h
|
||||
|
||||
#include "mozilla/layers/LayersMessages.h"
|
||||
|
||||
extern "C" {
|
||||
bool is_in_compositor_thread();
|
||||
void* get_proc_address_from_glcontext(void* glcontext_ptr, const char* procname);
|
||||
@ -39,6 +42,42 @@ struct WRColor {
|
||||
}
|
||||
};
|
||||
|
||||
struct WRGlyphInstance {
|
||||
uint32_t index;
|
||||
float x;
|
||||
float y;
|
||||
|
||||
bool operator==(const WRGlyphInstance& other) const {
|
||||
return index == other.index &&
|
||||
x == other.x &&
|
||||
y == other.y;
|
||||
}
|
||||
};
|
||||
|
||||
// Note that the type is slightly different than
|
||||
// the definition in bindings.rs. WRGlyphInstance
|
||||
// versus GlyphInstance, but their layout is the same.
|
||||
// So we're really overlapping the types for the same memory.
|
||||
struct WRGlyphArray {
|
||||
WRColor color;
|
||||
nsTArray<WRGlyphInstance> glyphs;
|
||||
|
||||
bool operator==(const WRGlyphArray& other) const {
|
||||
if (!(color == other.color) ||
|
||||
(glyphs.Length() != other.glyphs.Length())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < glyphs.Length(); i++) {
|
||||
if (!(glyphs[i] == other.glyphs[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
enum WRBorderStyle {
|
||||
None,
|
||||
Solid,
|
||||
@ -238,6 +277,14 @@ WR_INLINE void
|
||||
wr_profiler_set_enabled(wrwindowstate* wrWindow, bool enabled)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE void
|
||||
wr_dp_push_text(wrwindowstate* wrWindow, wrstate* wrState,
|
||||
WRRect bounds, WRRect clip,
|
||||
WRColor color, const WRGlyphInstance* glyphs,
|
||||
uint32_t glyph_count, float glyph_size,
|
||||
uint8_t* font_buffer, uint32_t buffer_size)
|
||||
WR_FUNC;
|
||||
|
||||
#undef WR_FUNC
|
||||
}
|
||||
#endif
|
||||
|
@ -4994,7 +4994,9 @@ nsDisplayText::nsDisplayText(nsDisplayListBuilder* aBuilder, nsTextFrame* aFrame
|
||||
GlyphArray* g = mGlyphs.AppendElement();
|
||||
std::vector<Glyph> glyphs;
|
||||
Color color;
|
||||
if (!capture->ContainsOnlyColoredGlyphs(mFont, color, glyphs)) {
|
||||
if (!capture->ContainsOnlyColoredGlyphs(mFont, color, glyphs)
|
||||
|| !mFont->CanSerialize()
|
||||
|| XRE_IsParentProcess()) {
|
||||
mFont = nullptr;
|
||||
mGlyphs.Clear();
|
||||
} else {
|
||||
@ -5011,7 +5013,7 @@ nsDisplayText::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
const ContainerLayerParameters& aParameters)
|
||||
{
|
||||
if (mFont) {
|
||||
return mozilla::LAYER_INACTIVE;
|
||||
return mozilla::LAYER_ACTIVE;
|
||||
}
|
||||
MOZ_ASSERT(mMergedFrames.IsEmpty());
|
||||
return mozilla::LAYER_NONE;
|
||||
|
Loading…
Reference in New Issue
Block a user