Bug 1389149 - Add WR bindings for setting hit-test info and doing hit-tests. r=mstange

This exposes some functions on wr::DisplayListBuilder to set hit-test
info and to do hit-tests.

The mechanism to set hit-test info is made a little more generic than is
actually used in this patchset, because doing it this way allows for
more optimization possibilities.
Specifically, the API allows setting some hit-testing state which is then
applied to all display items that are created until that state is
updated or cleared. An alternative would be to specify the hit-testing
state explicitly when creating particular display items; however doing
that would force the call sites that create the display items to compute
or obtain the hit-testing state, which would make the code less
encapsulated and harder to refactor/optimize.

MozReview-Commit-ID: EJoCFv83iu8

--HG--
extra : rebase_source : d2a117a52144f76dcc312de2a4047298e78135cb
This commit is contained in:
Kartikaya Gupta 2017-11-15 11:39:44 -05:00
parent 26f0373ad0
commit a02e29e13b
4 changed files with 121 additions and 1 deletions

View File

@ -11,7 +11,6 @@
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/widget/CompositorWidget.h"
#include "mozilla/widget/CompositorWidget.h"
#include "mozilla/layers/SynchronousTask.h"
#define WRDL_LOG(...)
@ -222,6 +221,18 @@ WebRenderAPI::UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
wr_scroll_layer_with_id(mDocHandle, aPipelineId, aScrollId, aScrollPosition);
}
bool
WebRenderAPI::HitTest(const wr::WorldPoint& aPoint,
wr::WrPipelineId& aOutPipelineId,
layers::FrameMetrics::ViewID& aOutScrollId,
gfx::CompositorHitTestInfo& aOutHitInfo)
{
static_assert(sizeof(gfx::CompositorHitTestInfo) == sizeof(uint8_t),
"CompositorHitTestInfo should be u8-sized");
return wr_api_hit_test(mDocHandle, aPoint,
&aOutPipelineId, &aOutScrollId, (uint8_t*)&aOutHitInfo);
}
void
WebRenderAPI::GenerateFrame()
{
@ -1248,5 +1259,20 @@ DisplayListBuilder::TopmostIsClip()
return mClipStack.back().is<wr::WrClipId>();
}
void
DisplayListBuilder::SetHitTestInfo(const layers::FrameMetrics::ViewID& aScrollId,
gfx::CompositorHitTestInfo aHitInfo)
{
static_assert(sizeof(gfx::CompositorHitTestInfo) == sizeof(uint8_t),
"CompositorHitTestInfo should be u8-sized");
wr_set_item_tag(mWrState, aScrollId, static_cast<uint8_t>(aHitInfo));
}
void
DisplayListBuilder::ClearHitTestInfo()
{
wr_clear_item_tag(mWrState);
}
} // namespace wr
} // namespace mozilla

View File

@ -12,6 +12,7 @@
#include <unordered_set>
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/gfx/CompositorHitTestInfo.h"
#include "mozilla/layers/SyncObject.h"
#include "mozilla/Range.h"
#include "mozilla/webrender/webrender_ffi.h"
@ -143,6 +144,10 @@ public:
void UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
const layers::FrameMetrics::ViewID& aScrollId,
const wr::LayoutPoint& aScrollPosition);
bool HitTest(const wr::WorldPoint& aPoint,
wr::WrPipelineId& aOutPipelineId,
layers::FrameMetrics::ViewID& aOutScrollId,
gfx::CompositorHitTestInfo& aOutHitInfo);
void GenerateFrame();
void GenerateFrame(const nsTArray<wr::WrOpacityProperty>& aOpacityArray,
@ -421,6 +426,13 @@ public:
// If the topmost item on the stack is a clip or a scroll layer
bool TopmostIsClip();
// Set the hit-test info to be used for all display items until the next call
// to SetHitTestInfo or ClearHitTestInfo.
void SetHitTestInfo(const layers::FrameMetrics::ViewID& aScrollId,
gfx::CompositorHitTestInfo aHitInfo);
// Clears the hit-test info so that subsequent display items will not have it.
void ClearHitTestInfo();
// Try to avoid using this when possible.
wr::WrState* Raw() { return mWrState; }

View File

@ -1190,6 +1190,7 @@ impl WebRenderFrameBuilder {
pub struct WrState {
pipeline_id: WrPipelineId,
frame_builder: WebRenderFrameBuilder,
current_tag: Option<ItemTag>,
}
#[no_mangle]
@ -1203,6 +1204,7 @@ pub extern "C" fn wr_state_new(pipeline_id: WrPipelineId,
frame_builder: WebRenderFrameBuilder::with_capacity(pipeline_id,
content_size,
capacity),
current_tag: None,
});
Box::into_raw(state)
@ -1292,6 +1294,7 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::new(bounds);
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
@ -1482,6 +1485,7 @@ pub extern "C" fn wr_dp_push_iframe(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::new(rect);
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder.dl_builder.push_iframe(&prim_info, pipeline_id);
}
@ -1495,6 +1499,7 @@ pub extern "C" fn wr_dp_push_rect(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder.dl_builder.push_rect(&prim_info,
color);
}
@ -1521,6 +1526,7 @@ pub extern "C" fn wr_dp_push_image(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_image(&prim_info,
@ -1545,6 +1551,7 @@ pub extern "C" fn wr_dp_push_yuv_planar_image(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_yuv_image(&prim_info,
@ -1567,6 +1574,7 @@ pub extern "C" fn wr_dp_push_yuv_NV12_image(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_yuv_image(&prim_info,
@ -1588,6 +1596,7 @@ pub extern "C" fn wr_dp_push_yuv_interleaved_image(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_yuv_image(&prim_info,
@ -1612,6 +1621,7 @@ pub extern "C" fn wr_dp_push_text(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_text(&prim_info,
@ -1631,6 +1641,7 @@ pub extern "C" fn wr_dp_push_shadow(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder.dl_builder.push_shadow(&prim_info, shadow.into());
}
@ -1654,6 +1665,7 @@ pub extern "C" fn wr_dp_push_line(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(*bounds, (*clip).into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_line(&prim_info,
@ -1686,6 +1698,7 @@ pub extern "C" fn wr_dp_push_border(state: &mut WrState,
});
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_border(&prim_info,
@ -1716,6 +1729,7 @@ pub extern "C" fn wr_dp_push_border_image(state: &mut WrState,
});
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_border(&prim_info,
@ -1752,6 +1766,7 @@ pub extern "C" fn wr_dp_push_border_gradient(state: &mut WrState,
});
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_border(&prim_info,
@ -1789,6 +1804,7 @@ pub extern "C" fn wr_dp_push_border_radial_gradient(state: &mut WrState,
});
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_border(&prim_info,
@ -1821,6 +1837,7 @@ pub extern "C" fn wr_dp_push_linear_gradient(state: &mut WrState,
extend_mode.into());
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_gradient(&prim_info,
@ -1854,6 +1871,7 @@ pub extern "C" fn wr_dp_push_radial_gradient(state: &mut WrState,
extend_mode.into());
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_radial_gradient(&prim_info,
@ -1878,6 +1896,7 @@ pub extern "C" fn wr_dp_push_box_shadow(state: &mut WrState,
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
prim_info.tag = state.current_tag;
state.frame_builder
.dl_builder
.push_box_shadow(&prim_info,
@ -1905,6 +1924,38 @@ pub unsafe extern "C" fn wr_api_finalize_builder(state: &mut WrState,
*dl_descriptor = descriptor;
}
#[no_mangle]
pub extern "C" fn wr_set_item_tag(state: &mut WrState,
scroll_id: u64,
hit_info: u8) {
state.current_tag = Some((scroll_id, hit_info));
}
#[no_mangle]
pub extern "C" fn wr_clear_item_tag(state: &mut WrState) {
state.current_tag = None;
}
#[no_mangle]
pub extern "C" fn wr_api_hit_test(dh: &mut DocumentHandle,
point: WorldPoint,
out_pipeline_id: &mut WrPipelineId,
out_scroll_id: &mut u64,
out_hit_info: &mut u8) -> bool {
let result = dh.api.hit_test(dh.document_id, None, point, HitTestFlags::empty());
for item in &result.items {
// For now we should never be getting results back for which the tag is
// 0 (== CompositorHitTestInfo::eInvisibleToHitTest). In the future if
// we allow this, we'll want to |continue| on the loop in this scenario.
debug_assert!(item.tag.1 != 0);
*out_pipeline_id = item.pipeline;
*out_scroll_id = item.tag.0;
*out_hit_info = item.tag.1;
return true;
}
return false;
}
pub type VecU8 = Vec<u8>;
pub type ArcVecU8 = Arc<VecU8>;

View File

@ -438,6 +438,19 @@ struct WrTransformProperty {
typedef IdNamespace WrIdNamespace;
// A 2d Point tagged with a unit.
struct TypedPoint2D_f32__WorldPixel {
float x;
float y;
bool operator==(const TypedPoint2D_f32__WorldPixel& aOther) const {
return x == aOther.x &&
y == aOther.y;
}
};
typedef TypedPoint2D_f32__WorldPixel WorldPoint;
// Represents RGBA screen colors with floating point numbers.
//
// All components must be between 0.0 and 1.0.
@ -1022,6 +1035,14 @@ WR_INLINE
WrIdNamespace wr_api_get_namespace(DocumentHandle *aDh)
WR_FUNC;
WR_INLINE
bool wr_api_hit_test(DocumentHandle *aDh,
WorldPoint aPoint,
WrPipelineId *aOutPipelineId,
uint64_t *aOutScrollId,
uint8_t *aOutHitInfo)
WR_FUNC;
WR_INLINE
void wr_api_remove_pipeline(DocumentHandle *aDh,
WrPipelineId aPipelineId)
@ -1069,6 +1090,10 @@ void wr_api_update_resources(DocumentHandle *aDh,
ResourceUpdates *aResources)
WR_FUNC;
WR_INLINE
void wr_clear_item_tag(WrState *aState)
WR_FUNC;
WR_INLINE
void wr_dec_ref_arc(const VecU8 *aArc)
WR_FUNC;
@ -1541,6 +1566,12 @@ void wr_scroll_layer_with_id(DocumentHandle *aDh,
LayoutPoint aNewScrollOrigin)
WR_FUNC;
WR_INLINE
void wr_set_item_tag(WrState *aState,
uint64_t aScrollId,
uint8_t aHitInfo)
WR_FUNC;
WR_INLINE
void wr_shutdown_external_log_handler()
WR_FUNC;