зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1653166 - Add transforms to WebRender Compositor API. r=gw,mstange,sotaro
Differential Revision: https://phabricator.services.mozilla.com/D84328
This commit is contained in:
Родитель
72cda2d18d
Коммит
01b5738a5d
|
@ -115,13 +115,20 @@ class NativeLayer {
|
|||
virtual bool IsOpaque() = 0;
|
||||
|
||||
// The location of the layer, in integer device pixels.
|
||||
// This is applied to the layer, before the transform is applied.
|
||||
virtual void SetPosition(const gfx::IntPoint& aPosition) = 0;
|
||||
virtual gfx::IntPoint GetPosition() = 0;
|
||||
|
||||
// Sets a transformation to apply to the Layer. This gets applied to
|
||||
// coordinates with the position applied, but before clipping is
|
||||
// applied.
|
||||
virtual void SetTransform(const gfx::Matrix4x4& aTransform) = 0;
|
||||
virtual gfx::Matrix4x4 GetTransform() = 0;
|
||||
|
||||
virtual gfx::IntRect GetRect() = 0;
|
||||
|
||||
// Set an optional clip rect on the layer. The clip rect is in the same
|
||||
// coordinate space as the layer rect.
|
||||
// Set an optional clip rect on the layer. The clip rect is in post-transform
|
||||
// coordinate space
|
||||
virtual void SetClipRect(const Maybe<gfx::IntRect>& aClipRect) = 0;
|
||||
virtual Maybe<gfx::IntRect> ClipRect() = 0;
|
||||
|
||||
|
|
|
@ -185,6 +185,8 @@ class NativeLayerCA : public NativeLayer {
|
|||
gfx::IntSize GetSize() override;
|
||||
void SetPosition(const gfx::IntPoint& aPosition) override;
|
||||
gfx::IntPoint GetPosition() override;
|
||||
void SetTransform(const gfx::Matrix4x4& aTransform) override;
|
||||
gfx::Matrix4x4 GetTransform() override;
|
||||
gfx::IntRect GetRect() override;
|
||||
RefPtr<gfx::DrawTarget> NextSurfaceAsDrawTarget(
|
||||
const gfx::IntRect& aDisplayRect, const gfx::IntRegion& aUpdateRegion,
|
||||
|
@ -269,6 +271,7 @@ class NativeLayerCA : public NativeLayer {
|
|||
// before the call.
|
||||
void ApplyChanges(const gfx::IntSize& aSize, bool aIsOpaque,
|
||||
const gfx::IntPoint& aPosition,
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
const gfx::IntRect& aDisplayRect,
|
||||
const Maybe<gfx::IntRect>& aClipRect, float aBackingScale,
|
||||
bool aSurfaceIsFlipped,
|
||||
|
@ -284,6 +287,7 @@ class NativeLayerCA : public NativeLayer {
|
|||
CALayer* mOpaquenessTintLayer = nullptr; // strong
|
||||
|
||||
bool mMutatedPosition = true;
|
||||
bool mMutatedTransform = true;
|
||||
bool mMutatedDisplayRect = true;
|
||||
bool mMutatedClipRect = true;
|
||||
bool mMutatedBackingScale = true;
|
||||
|
@ -352,6 +356,7 @@ class NativeLayerCA : public NativeLayer {
|
|||
Representation mOffscreenRepresentation;
|
||||
|
||||
gfx::IntPoint mPosition;
|
||||
gfx::Matrix4x4 mTransform;
|
||||
gfx::IntRect mDisplayRect;
|
||||
const gfx::IntSize mSize;
|
||||
Maybe<gfx::IntRect> mClipRect;
|
||||
|
|
|
@ -32,6 +32,7 @@ using gfx::IntPoint;
|
|||
using gfx::IntSize;
|
||||
using gfx::IntRect;
|
||||
using gfx::IntRegion;
|
||||
using gfx::Matrix4x4;
|
||||
using gfx::SurfaceFormat;
|
||||
using gl::GLContext;
|
||||
using gl::GLContextCGL;
|
||||
|
@ -427,6 +428,21 @@ IntPoint NativeLayerCA::GetPosition() {
|
|||
return mPosition;
|
||||
}
|
||||
|
||||
void NativeLayerCA::SetTransform(const Matrix4x4& aTransform) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
MOZ_ASSERT(aTransform.IsRectilinear());
|
||||
|
||||
if (aTransform != mTransform) {
|
||||
mTransform = aTransform;
|
||||
ForAllRepresentations([&](Representation& r) { r.mMutatedTransform = true; });
|
||||
}
|
||||
}
|
||||
|
||||
Matrix4x4 NativeLayerCA::GetTransform() {
|
||||
MutexAutoLock lock(mMutex);
|
||||
return mTransform;
|
||||
}
|
||||
|
||||
IntRect NativeLayerCA::GetRect() {
|
||||
MutexAutoLock lock(mMutex);
|
||||
return IntRect(mPosition, mSize);
|
||||
|
@ -671,7 +687,7 @@ void NativeLayerCA::ForAllRepresentations(F aFn) {
|
|||
void NativeLayerCA::ApplyChanges(WhichRepresentation aRepresentation) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
GetRepresentation(aRepresentation)
|
||||
.ApplyChanges(mSize, mIsOpaque, mPosition, mDisplayRect, mClipRect, mBackingScale,
|
||||
.ApplyChanges(mSize, mIsOpaque, mPosition, mTransform, mDisplayRect, mClipRect, mBackingScale,
|
||||
mSurfaceIsFlipped, mFrontSurface ? mFrontSurface->mSurface : nullptr);
|
||||
}
|
||||
|
||||
|
@ -680,12 +696,10 @@ CALayer* NativeLayerCA::UnderlyingCALayer(WhichRepresentation aRepresentation) {
|
|||
return GetRepresentation(aRepresentation).UnderlyingCALayer();
|
||||
}
|
||||
|
||||
void NativeLayerCA::Representation::ApplyChanges(const IntSize& aSize, bool aIsOpaque,
|
||||
const IntPoint& aPosition,
|
||||
const IntRect& aDisplayRect,
|
||||
const Maybe<IntRect>& aClipRect,
|
||||
float aBackingScale, bool aSurfaceIsFlipped,
|
||||
CFTypeRefPtr<IOSurfaceRef> aFrontSurface) {
|
||||
void NativeLayerCA::Representation::ApplyChanges(
|
||||
const IntSize& aSize, bool aIsOpaque, const IntPoint& aPosition, const Matrix4x4& aTransform,
|
||||
const IntRect& aDisplayRect, const Maybe<IntRect>& aClipRect, float aBackingScale,
|
||||
bool aSurfaceIsFlipped, CFTypeRefPtr<IOSurfaceRef> aFrontSurface) {
|
||||
if (!mWrappingCALayer) {
|
||||
mWrappingCALayer = [[CALayer layer] retain];
|
||||
mWrappingCALayer.position = NSZeroPoint;
|
||||
|
@ -747,17 +761,26 @@ void NativeLayerCA::Representation::ApplyChanges(const IntSize& aSize, bool aIsO
|
|||
mContentCALayer.contentsScale = aBackingScale;
|
||||
}
|
||||
|
||||
if (mMutatedBackingScale || mMutatedPosition || mMutatedDisplayRect || mMutatedClipRect) {
|
||||
auto clipFromDisplayRect = aDisplayRect.IsEqualInterior(IntRect({}, aSize))
|
||||
? Nothing()
|
||||
: Some(aDisplayRect + aPosition);
|
||||
if (mMutatedBackingScale || mMutatedPosition || mMutatedDisplayRect || mMutatedClipRect ||
|
||||
mMutatedTransform || mMutatedSurfaceIsFlipped) {
|
||||
Maybe<IntRect> clipFromDisplayRect;
|
||||
if (!aDisplayRect.IsEqualInterior(IntRect({}, aSize))) {
|
||||
// When the display rect is a subset of the layer, then we want to guarantee that no
|
||||
// pixels outside that rect are sampled, since they might be uninitialized.
|
||||
// Transforming the display rect into a post-transform clip only maintains this if
|
||||
// it's an integer translation, which is all we support for this case currently.
|
||||
MOZ_ASSERT(aTransform.Is2DIntegerTranslation());
|
||||
clipFromDisplayRect =
|
||||
Some(RoundedToInt(aTransform.TransformBounds(IntRectToRect(aDisplayRect + aPosition))));
|
||||
}
|
||||
|
||||
auto effectiveClip = IntersectMaybeRects(aClipRect, clipFromDisplayRect);
|
||||
auto globalClipOrigin = effectiveClip ? effectiveClip->TopLeft() : aPosition;
|
||||
auto globalLayerOrigin = aPosition;
|
||||
auto clipToLayerOffset = globalLayerOrigin - globalClipOrigin;
|
||||
auto globalClipOrigin = effectiveClip ? effectiveClip->TopLeft() : IntPoint();
|
||||
auto clipToLayerOffset = -globalClipOrigin;
|
||||
|
||||
mWrappingCALayer.position =
|
||||
CGPointMake(globalClipOrigin.x / aBackingScale, globalClipOrigin.y / aBackingScale);
|
||||
|
||||
if (effectiveClip) {
|
||||
mWrappingCALayer.masksToBounds = YES;
|
||||
mWrappingCALayer.bounds = CGRectMake(0, 0, effectiveClip->Width() / aBackingScale,
|
||||
|
@ -767,18 +790,36 @@ void NativeLayerCA::Representation::ApplyChanges(const IntSize& aSize, bool aIsO
|
|||
}
|
||||
mContentCALayer.position =
|
||||
CGPointMake(clipToLayerOffset.x / aBackingScale, clipToLayerOffset.y / aBackingScale);
|
||||
mContentCALayer.position = CGPointMake(0, 0);
|
||||
if (mOpaquenessTintLayer) {
|
||||
mOpaquenessTintLayer.position = mContentCALayer.position;
|
||||
}
|
||||
}
|
||||
|
||||
if (mMutatedBackingScale || mMutatedSurfaceIsFlipped) {
|
||||
Matrix4x4 transform = aTransform;
|
||||
transform.PreTranslate(aPosition.x, aPosition.y, 0);
|
||||
transform.PostTranslate(clipToLayerOffset.x, clipToLayerOffset.y, 0);
|
||||
|
||||
if (aSurfaceIsFlipped) {
|
||||
CGFloat height = aSize.height / aBackingScale;
|
||||
mContentCALayer.affineTransform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, height);
|
||||
} else {
|
||||
mContentCALayer.affineTransform = CGAffineTransformIdentity;
|
||||
transform.PreTranslate(0, aSize.height, 0).PreScale(1, -1, 1);
|
||||
}
|
||||
|
||||
CATransform3D transformCA{transform._11,
|
||||
transform._12,
|
||||
transform._13,
|
||||
transform._14,
|
||||
transform._21,
|
||||
transform._22,
|
||||
transform._23,
|
||||
transform._24,
|
||||
transform._31,
|
||||
transform._32,
|
||||
transform._33,
|
||||
transform._34,
|
||||
transform._41 / aBackingScale,
|
||||
transform._42 / aBackingScale,
|
||||
transform._43,
|
||||
transform._44};
|
||||
mContentCALayer.transform = transformCA;
|
||||
}
|
||||
|
||||
if (mMutatedFrontSurface) {
|
||||
|
@ -786,6 +827,7 @@ void NativeLayerCA::Representation::ApplyChanges(const IntSize& aSize, bool aIsO
|
|||
}
|
||||
|
||||
mMutatedPosition = false;
|
||||
mMutatedTransform = false;
|
||||
mMutatedBackingScale = false;
|
||||
mMutatedSurfaceIsFlipped = false;
|
||||
mMutatedDisplayRect = false;
|
||||
|
|
|
@ -335,8 +335,18 @@ void DCLayerTree::DestroyTile(wr::NativeSurfaceId aId, int aX, int aY) {
|
|||
surface->DestroyTile(aX, aY);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline D2D1_RECT_F D2DRect(const T& aRect) {
|
||||
return D2D1::RectF(aRect.X(), aRect.Y(), aRect.XMost(), aRect.YMost());
|
||||
}
|
||||
|
||||
static inline D2D1_MATRIX_3X2_F D2DMatrix(const gfx::Matrix& aTransform) {
|
||||
return D2D1::Matrix3x2F(aTransform._11, aTransform._12, aTransform._21,
|
||||
aTransform._22, aTransform._31, aTransform._32);
|
||||
}
|
||||
|
||||
void DCLayerTree::AddSurface(wr::NativeSurfaceId aId,
|
||||
wr::DeviceIntPoint aPosition,
|
||||
const wr::CompositorSurfaceTransform& aTransform,
|
||||
wr::DeviceIntRect aClipRect) {
|
||||
auto it = mDCSurfaces.find(aId);
|
||||
MOZ_RELEASE_ASSERT(it != mDCSurfaces.end());
|
||||
|
@ -344,22 +354,33 @@ void DCLayerTree::AddSurface(wr::NativeSurfaceId aId,
|
|||
const auto visual = surface->GetVisual();
|
||||
|
||||
wr::DeviceIntPoint virtualOffset = surface->GetVirtualOffset();
|
||||
aPosition.x -= virtualOffset.x;
|
||||
aPosition.y -= virtualOffset.y;
|
||||
|
||||
// Place the visual - this changes frame to frame based on scroll position
|
||||
// of the slice.
|
||||
visual->SetOffsetX(aPosition.x);
|
||||
visual->SetOffsetY(aPosition.y);
|
||||
gfx::Matrix transform(aTransform.m11, aTransform.m12, aTransform.m21,
|
||||
aTransform.m22, aTransform.m41, aTransform.m42);
|
||||
transform.PreTranslate(-virtualOffset.x, -virtualOffset.y);
|
||||
|
||||
// The DirectComposition API applies clipping *before* any transforms/offset,
|
||||
// whereas we want the clip applied after.
|
||||
// Right now, we only support rectilinear transforms, and then we transform
|
||||
// our clip into pre-transform coordinate space for it to be applied there.
|
||||
// DirectComposition does have an option for pre-transform clipping, if you
|
||||
// create an explicit IDCompositionEffectGroup object and set a 3D transform
|
||||
// on that. I suspect that will perform worse though, so we should only do
|
||||
// that for complex transforms (which are never provided right now).
|
||||
MOZ_ASSERT(transform.IsRectilinear());
|
||||
gfx::Rect clip = transform.Inverse().TransformBounds(
|
||||
gfx::Rect(aClipRect.origin.x, aClipRect.origin.y, aClipRect.size.width,
|
||||
aClipRect.size.height));
|
||||
clip.Round();
|
||||
// Set the clip rect - converting from world space to the pre-offset space
|
||||
// that DC requires for rectangle clips.
|
||||
D2D_RECT_F clip_rect;
|
||||
clip_rect.left = aClipRect.origin.x - aPosition.x;
|
||||
clip_rect.top = aClipRect.origin.y - aPosition.y;
|
||||
clip_rect.right = clip_rect.left + aClipRect.size.width;
|
||||
clip_rect.bottom = clip_rect.top + aClipRect.size.height;
|
||||
visual->SetClip(clip_rect);
|
||||
visual->SetClip(D2DRect(clip));
|
||||
|
||||
// TODO: The input matrix is a 4x4, but we only support a 3x2 at
|
||||
// the D3D API level (unless we QI to IDCompositionVisual3, which might
|
||||
// not be available?).
|
||||
// Should we assert here, or restrict at the WR API level.
|
||||
visual->SetTransform(D2DMatrix(transform));
|
||||
|
||||
mCurrentLayers.push_back(aId);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,8 @@ class DCLayerTree {
|
|||
void DestroySurface(NativeSurfaceId aId);
|
||||
void CreateTile(wr::NativeSurfaceId aId, int32_t aX, int32_t aY);
|
||||
void DestroyTile(wr::NativeSurfaceId aId, int32_t aX, int32_t aY);
|
||||
void AddSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aPosition,
|
||||
void AddSurface(wr::NativeSurfaceId aId,
|
||||
const wr::CompositorSurfaceTransform& aTransform,
|
||||
wr::DeviceIntRect aClipRect);
|
||||
|
||||
gl::GLContext* GetGLContext() const { return mGL; }
|
||||
|
|
|
@ -29,10 +29,10 @@ namespace mozilla {
|
|||
namespace wr {
|
||||
|
||||
void wr_compositor_add_surface(void* aCompositor, wr::NativeSurfaceId aId,
|
||||
wr::DeviceIntPoint aPosition,
|
||||
const wr::CompositorSurfaceTransform* aTransform,
|
||||
wr::DeviceIntRect aClipRect) {
|
||||
RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor);
|
||||
compositor->AddSurface(aId, aPosition, aClipRect);
|
||||
compositor->AddSurface(aId, *aTransform, aClipRect);
|
||||
}
|
||||
|
||||
void wr_compositor_begin_frame(void* aCompositor) {
|
||||
|
|
|
@ -108,7 +108,8 @@ class RenderCompositor {
|
|||
virtual void DestroySurface(NativeSurfaceId aId) {}
|
||||
virtual void CreateTile(wr::NativeSurfaceId, int32_t aX, int32_t aY) {}
|
||||
virtual void DestroyTile(wr::NativeSurfaceId, int32_t aX, int32_t aY) {}
|
||||
virtual void AddSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aPosition,
|
||||
virtual void AddSurface(wr::NativeSurfaceId aId,
|
||||
const wr::CompositorSurfaceTransform& aTransform,
|
||||
wr::DeviceIntRect aClipRect) {}
|
||||
virtual void EnableNativeCompositor(bool aEnable) {}
|
||||
virtual void DeInit() {}
|
||||
|
|
|
@ -864,10 +864,10 @@ void RenderCompositorANGLE::DestroyTile(wr::NativeSurfaceId aId, int aX,
|
|||
mDCLayerTree->DestroyTile(aId, aX, aY);
|
||||
}
|
||||
|
||||
void RenderCompositorANGLE::AddSurface(wr::NativeSurfaceId aId,
|
||||
wr::DeviceIntPoint aPosition,
|
||||
wr::DeviceIntRect aClipRect) {
|
||||
mDCLayerTree->AddSurface(aId, aPosition, aClipRect);
|
||||
void RenderCompositorANGLE::AddSurface(
|
||||
wr::NativeSurfaceId aId, const wr::CompositorSurfaceTransform& aTransform,
|
||||
wr::DeviceIntRect aClipRect) {
|
||||
mDCLayerTree->AddSurface(aId, aTransform, aClipRect);
|
||||
}
|
||||
|
||||
CompositorCapabilities RenderCompositorANGLE::GetCompositorCapabilities() {
|
||||
|
|
|
@ -81,7 +81,8 @@ class RenderCompositorANGLE : public RenderCompositor {
|
|||
void DestroySurface(NativeSurfaceId aId) override;
|
||||
void CreateTile(wr::NativeSurfaceId aId, int32_t aX, int32_t aY) override;
|
||||
void DestroyTile(wr::NativeSurfaceId aId, int32_t aX, int32_t aY) override;
|
||||
void AddSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aPosition,
|
||||
void AddSurface(wr::NativeSurfaceId aId,
|
||||
const wr::CompositorSurfaceTransform& aTransform,
|
||||
wr::DeviceIntRect aClipRect) override;
|
||||
void EnableNativeCompositor(bool aEnable) override;
|
||||
CompositorCapabilities GetCompositorCapabilities() override;
|
||||
|
|
|
@ -245,26 +245,32 @@ void RenderCompositorNative::DestroyTile(wr::NativeSurfaceId aId, int aX,
|
|||
layer->DiscardBackbuffers();
|
||||
}
|
||||
|
||||
void RenderCompositorNative::AddSurface(wr::NativeSurfaceId aId,
|
||||
wr::DeviceIntPoint aPosition,
|
||||
wr::DeviceIntRect aClipRect) {
|
||||
void RenderCompositorNative::AddSurface(
|
||||
wr::NativeSurfaceId aId, const wr::CompositorSurfaceTransform& aTransform,
|
||||
wr::DeviceIntRect aClipRect) {
|
||||
MOZ_RELEASE_ASSERT(!mCurrentlyBoundNativeLayer);
|
||||
|
||||
auto surfaceCursor = mSurfaces.find(aId);
|
||||
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
|
||||
const Surface& surface = surfaceCursor->second;
|
||||
|
||||
Matrix4x4 transform(
|
||||
aTransform.m11, aTransform.m12, aTransform.m13, aTransform.m14,
|
||||
aTransform.m21, aTransform.m22, aTransform.m23, aTransform.m24,
|
||||
aTransform.m31, aTransform.m32, aTransform.m33, aTransform.m34,
|
||||
aTransform.m41, aTransform.m42, aTransform.m43, aTransform.m44);
|
||||
|
||||
for (auto it = surface.mNativeLayers.begin();
|
||||
it != surface.mNativeLayers.end(); ++it) {
|
||||
RefPtr<layers::NativeLayer> layer = it->second;
|
||||
gfx::IntSize layerSize = layer->GetSize();
|
||||
gfx::IntPoint layerPosition(
|
||||
aPosition.x + surface.mTileSize.width * it->first.mX,
|
||||
aPosition.y + surface.mTileSize.height * it->first.mY);
|
||||
gfx::IntPoint layerPosition(surface.mTileSize.width * it->first.mX,
|
||||
surface.mTileSize.height * it->first.mY);
|
||||
layer->SetPosition(layerPosition);
|
||||
gfx::IntRect clipRect(aClipRect.origin.x, aClipRect.origin.y,
|
||||
aClipRect.size.width, aClipRect.size.height);
|
||||
layer->SetClipRect(Some(clipRect));
|
||||
layer->SetTransform(transform);
|
||||
mAddedLayers.AppendElement(layer);
|
||||
|
||||
mAddedPixelCount += layerSize.width * layerSize.height;
|
||||
|
|
|
@ -53,7 +53,8 @@ class RenderCompositorNative : public RenderCompositor {
|
|||
void DestroySurface(NativeSurfaceId aId) override;
|
||||
void CreateTile(wr::NativeSurfaceId aId, int32_t aX, int32_t aY) override;
|
||||
void DestroyTile(wr::NativeSurfaceId aId, int32_t aX, int32_t aY) override;
|
||||
void AddSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aPosition,
|
||||
void AddSurface(wr::NativeSurfaceId aId,
|
||||
const wr::CompositorSurfaceTransform& aTransform,
|
||||
wr::DeviceIntRect aClipRect) override;
|
||||
CompositorCapabilities GetCompositorCapabilities() override;
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ use webrender::{
|
|||
CompositorCapabilities, CompositorConfig, DebugFlags, Device, FastHashMap, NativeSurfaceId, NativeSurfaceInfo,
|
||||
NativeTileId, PipelineInfo, ProfilerHooks, RecordedFrameHandle, Renderer, RendererOptions, RendererStats,
|
||||
SceneBuilderHooks, ShaderPrecacheFlags, Shaders, ThreadListener, UploadMethod, WrShaders, ONE_TIME_USAGE_HINT,
|
||||
CompositorSurfaceTransform,
|
||||
};
|
||||
use wr_malloc_size_of::MallocSizeOfOps;
|
||||
|
||||
|
@ -1211,7 +1212,7 @@ extern "C" {
|
|||
fn wr_compositor_add_surface(
|
||||
compositor: *mut c_void,
|
||||
id: NativeSurfaceId,
|
||||
position: DeviceIntPoint,
|
||||
transform: &CompositorSurfaceTransform,
|
||||
clip_rect: DeviceIntRect,
|
||||
);
|
||||
fn wr_compositor_end_frame(compositor: *mut c_void);
|
||||
|
@ -1294,9 +1295,9 @@ impl Compositor for WrCompositor {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_surface(&mut self, id: NativeSurfaceId, position: DeviceIntPoint, clip_rect: DeviceIntRect) {
|
||||
fn add_surface(&mut self, id: NativeSurfaceId, transform: CompositorSurfaceTransform, clip_rect: DeviceIntRect) {
|
||||
unsafe {
|
||||
wr_compositor_add_surface(self.0, id, position, clip_rect);
|
||||
wr_compositor_add_surface(self.0, id, &transform, clip_rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ use std::rc::Rc;
|
|||
use std::sync::{mpsc, Arc, Condvar, Mutex};
|
||||
use std::thread;
|
||||
use webrender::{
|
||||
api::units::*, Compositor, CompositorCapabilities, NativeSurfaceId, NativeSurfaceInfo, NativeTileId, ThreadListener,
|
||||
api::units::*, Compositor, CompositorCapabilities, NativeSurfaceId, NativeSurfaceInfo, NativeTileId,
|
||||
ThreadListener, CompositorSurfaceTransform
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -62,8 +63,8 @@ pub struct SwTile {
|
|||
}
|
||||
|
||||
impl SwTile {
|
||||
fn origin(&self, surface: &SwSurface, position: &DeviceIntPoint) -> DeviceIntPoint {
|
||||
DeviceIntPoint::new(self.x * surface.tile_size.width, self.y * surface.tile_size.height) + position.to_vector()
|
||||
fn origin(&self, surface: &SwSurface) -> DeviceIntPoint {
|
||||
DeviceIntPoint::new(self.x * surface.tile_size.width, self.y * surface.tile_size.height)
|
||||
}
|
||||
|
||||
/// Bounds used for determining overlap dependencies. This may either be the
|
||||
|
@ -73,10 +74,10 @@ impl SwTile {
|
|||
fn overlap_rect(
|
||||
&self,
|
||||
surface: &SwSurface,
|
||||
position: &DeviceIntPoint,
|
||||
transform: &CompositorSurfaceTransform,
|
||||
clip_rect: &DeviceIntRect,
|
||||
) -> Option<DeviceIntRect> {
|
||||
let origin = self.origin(surface, position);
|
||||
let origin = self.origin(surface);
|
||||
// If the tile was invalidated this frame, then we don't have precise
|
||||
// bounds. Instead, just use the default surface tile size.
|
||||
let bounds = if self.invalid.get() {
|
||||
|
@ -84,7 +85,8 @@ impl SwTile {
|
|||
} else {
|
||||
self.valid_rect.translate(origin.to_vector())
|
||||
};
|
||||
bounds.intersection(clip_rect)
|
||||
let device_rect = transform.transform_rect(&bounds.to_f32().cast_unit()).unwrap().round_out().to_i32();
|
||||
device_rect.cast_unit().intersection(clip_rect)
|
||||
}
|
||||
|
||||
/// Determine if the tile's bounds may overlap the dependency rect if it were
|
||||
|
@ -92,11 +94,11 @@ impl SwTile {
|
|||
fn may_overlap(
|
||||
&self,
|
||||
surface: &SwSurface,
|
||||
position: &DeviceIntPoint,
|
||||
transform: &CompositorSurfaceTransform,
|
||||
clip_rect: &DeviceIntRect,
|
||||
dep_rect: &DeviceIntRect,
|
||||
) -> bool {
|
||||
self.overlap_rect(surface, position, clip_rect)
|
||||
self.overlap_rect(surface, transform, clip_rect)
|
||||
.map_or(false, |r| r.intersects(dep_rect))
|
||||
}
|
||||
|
||||
|
@ -106,13 +108,12 @@ impl SwTile {
|
|||
fn composite_rects(
|
||||
&self,
|
||||
surface: &SwSurface,
|
||||
position: &DeviceIntPoint,
|
||||
transform: &CompositorSurfaceTransform,
|
||||
clip_rect: &DeviceIntRect,
|
||||
) -> Option<(DeviceIntRect, DeviceIntRect)> {
|
||||
let valid = self.valid_rect.translate(self.origin(surface, position).to_vector());
|
||||
valid
|
||||
.intersection(clip_rect)
|
||||
.map(|r| (r.translate(-valid.origin.to_vector()), r))
|
||||
let valid = self.valid_rect.translate(self.origin(surface).to_vector());
|
||||
let valid = transform.transform_rect(&valid.to_f32().cast_unit()).unwrap().round_out().to_i32();
|
||||
valid.cast_unit().intersection(clip_rect).map(|r| (r.translate(-valid.origin.to_vector().cast_unit()), r))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -392,7 +393,7 @@ pub struct SwCompositor {
|
|||
native_gl: Option<Rc<dyn gl::Gl>>,
|
||||
compositor: Option<WrCompositor>,
|
||||
surfaces: HashMap<NativeSurfaceId, SwSurface>,
|
||||
frame_surfaces: Vec<(NativeSurfaceId, DeviceIntPoint, DeviceIntRect)>,
|
||||
frame_surfaces: Vec<(NativeSurfaceId, CompositorSurfaceTransform, DeviceIntRect)>,
|
||||
cur_tile: NativeTileId,
|
||||
draw_tile: Option<DrawTileHelper>,
|
||||
/// The maximum tile size required for any of the allocated surfaces.
|
||||
|
@ -485,7 +486,7 @@ impl SwCompositor {
|
|||
/// in composition.
|
||||
fn get_overlaps(&self, overlap_rect: &DeviceIntRect) -> u32 {
|
||||
let mut overlaps = 0;
|
||||
for &(ref id, ref position, ref clip_rect) in &self.frame_surfaces {
|
||||
for &(ref id, ref transform, ref clip_rect) in &self.frame_surfaces {
|
||||
// If the surface's clip rect doesn't overlap the tile's rect,
|
||||
// then there is no need to check any tiles within the surface.
|
||||
if !overlap_rect.intersects(clip_rect) {
|
||||
|
@ -495,7 +496,8 @@ impl SwCompositor {
|
|||
for tile in &surface.tiles {
|
||||
// If there is a deferred tile that might overlap the destination rectangle,
|
||||
// record the overlap.
|
||||
if tile.overlaps.get() > 0 && tile.may_overlap(surface, position, clip_rect, overlap_rect) {
|
||||
if tile.overlaps.get() > 0 &&
|
||||
tile.may_overlap(surface, transform, clip_rect, overlap_rect) {
|
||||
overlaps += 1;
|
||||
}
|
||||
}
|
||||
|
@ -508,12 +510,12 @@ impl SwCompositor {
|
|||
fn queue_composite(
|
||||
&self,
|
||||
surface: &SwSurface,
|
||||
position: &DeviceIntPoint,
|
||||
transform: &CompositorSurfaceTransform,
|
||||
clip_rect: &DeviceIntRect,
|
||||
tile: &SwTile,
|
||||
) {
|
||||
if let Some(ref composite_thread) = self.composite_thread {
|
||||
if let Some((src_rect, dst_rect)) = tile.composite_rects(surface, position, clip_rect) {
|
||||
if let Some((src_rect, dst_rect)) = tile.composite_rects(surface, transform, clip_rect) {
|
||||
if let Some(texture) = self.gl.lock_texture(tile.color_id) {
|
||||
let framebuffer = self.locked_framebuffer.clone().unwrap();
|
||||
composite_thread.queue_composite(texture, framebuffer, src_rect, dst_rect, surface.is_opaque);
|
||||
|
@ -526,14 +528,14 @@ impl SwCompositor {
|
|||
/// within the surface being queued for composition this frame. If the tile is immediately
|
||||
/// ready to composite, then queue that now. Otherwise, set its draw order index for later
|
||||
/// composition.
|
||||
fn init_composites(&mut self, id: &NativeSurfaceId, position: &DeviceIntPoint, clip_rect: &DeviceIntRect) {
|
||||
fn init_composites(&mut self, id: &NativeSurfaceId, transform: &CompositorSurfaceTransform, clip_rect: &DeviceIntRect) {
|
||||
if self.composite_thread.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(surface) = self.surfaces.get(&id) {
|
||||
for tile in &surface.tiles {
|
||||
if let Some(overlap_rect) = tile.overlap_rect(surface, position, clip_rect) {
|
||||
if let Some(overlap_rect) = tile.overlap_rect(surface, transform, clip_rect) {
|
||||
let mut overlaps = self.get_overlaps(&overlap_rect);
|
||||
// Record an extra overlap for an invalid tile to track the tile's dependency
|
||||
// on its own future update.
|
||||
|
@ -542,7 +544,7 @@ impl SwCompositor {
|
|||
}
|
||||
if overlaps == 0 {
|
||||
// Not dependent on any tiles, so go ahead and composite now.
|
||||
self.queue_composite(surface, position, clip_rect, tile);
|
||||
self.queue_composite(surface, transform, clip_rect, tile);
|
||||
} else {
|
||||
// Has a dependency on some invalid tiles, so need to defer composition.
|
||||
tile.overlaps.set(overlaps);
|
||||
|
@ -565,7 +567,7 @@ impl SwCompositor {
|
|||
.iter()
|
||||
.skip_while(|&(ref id, _, _)| *id != tile_id.surface_id);
|
||||
let overlap_rect = match frame_surfaces.next() {
|
||||
Some(&(_, ref position, ref clip_rect)) => {
|
||||
Some(&(_, ref transform, ref clip_rect)) => {
|
||||
// Remove invalid tile's update dependency.
|
||||
if tile.invalid.get() {
|
||||
tile.overlaps.set(tile.overlaps.get() - 1);
|
||||
|
@ -575,9 +577,9 @@ impl SwCompositor {
|
|||
return;
|
||||
}
|
||||
// Otherwise, the tile's dependencies are all resolved, so composite it.
|
||||
self.queue_composite(surface, position, clip_rect, tile);
|
||||
self.queue_composite(surface, transform, clip_rect, tile);
|
||||
// Finally, get the tile's overlap rect used for tracking dependencies
|
||||
match tile.overlap_rect(surface, position, clip_rect) {
|
||||
match tile.overlap_rect(surface, transform, clip_rect) {
|
||||
Some(overlap_rect) => overlap_rect,
|
||||
None => return,
|
||||
}
|
||||
|
@ -591,7 +593,7 @@ impl SwCompositor {
|
|||
let mut flushed_rects = vec![overlap_rect];
|
||||
|
||||
// Check surfaces following the update in the frame list and see if they would overlap it.
|
||||
for &(ref id, ref position, ref clip_rect) in frame_surfaces {
|
||||
for &(ref id, ref transform, ref clip_rect) in frame_surfaces {
|
||||
// If the clip rect doesn't overlap the conservative bounds, we can skip the whole surface.
|
||||
if !flushed_bounds.intersects(clip_rect) {
|
||||
continue;
|
||||
|
@ -605,7 +607,7 @@ impl SwCompositor {
|
|||
continue;
|
||||
}
|
||||
// Get this tile's overlap rect for tracking dependencies
|
||||
let overlap_rect = match tile.overlap_rect(surface, position, clip_rect) {
|
||||
let overlap_rect = match tile.overlap_rect(surface, transform, clip_rect) {
|
||||
Some(overlap_rect) => overlap_rect,
|
||||
None => continue,
|
||||
};
|
||||
|
@ -624,7 +626,7 @@ impl SwCompositor {
|
|||
// If the count hit zero, it is ready to composite.
|
||||
tile.overlaps.set(overlaps);
|
||||
if overlaps == 0 {
|
||||
self.queue_composite(surface, position, clip_rect, tile);
|
||||
self.queue_composite(surface, transform, clip_rect, tile);
|
||||
// Record that the tile got flushed to update any downwind dependencies.
|
||||
flushed_bounds = flushed_bounds.union(&overlap_rect);
|
||||
flushed_rects.push(overlap_rect);
|
||||
|
@ -946,15 +948,15 @@ impl Compositor for SwCompositor {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_surface(&mut self, id: NativeSurfaceId, position: DeviceIntPoint, clip_rect: DeviceIntRect) {
|
||||
fn add_surface(&mut self, id: NativeSurfaceId, transform: CompositorSurfaceTransform, clip_rect: DeviceIntRect) {
|
||||
if let Some(compositor) = &mut self.compositor {
|
||||
compositor.add_surface(id, position, clip_rect);
|
||||
compositor.add_surface(id, transform, clip_rect);
|
||||
}
|
||||
|
||||
// Compute overlap dependencies and issue any initial composite jobs for the SwComposite thread.
|
||||
self.init_composites(&id, &position, &clip_rect);
|
||||
self.init_composites(&id, &transform, &clip_rect);
|
||||
|
||||
self.frame_surfaces.push((id, position, clip_rect));
|
||||
self.frame_surfaces.push((id, transform, clip_rect));
|
||||
}
|
||||
|
||||
fn end_frame(&mut self) {
|
||||
|
@ -967,7 +969,7 @@ impl Compositor for SwCompositor {
|
|||
draw_tile.enable(&viewport);
|
||||
let mut blend = false;
|
||||
native_gl.blend_func(gl::ONE, gl::ONE_MINUS_SRC_ALPHA);
|
||||
for &(ref id, ref position, ref clip_rect) in &self.frame_surfaces {
|
||||
for &(ref id, ref transform, ref clip_rect) in &self.frame_surfaces {
|
||||
if let Some(surface) = self.surfaces.get(id) {
|
||||
if surface.is_opaque {
|
||||
if blend {
|
||||
|
@ -979,7 +981,7 @@ impl Compositor for SwCompositor {
|
|||
blend = true;
|
||||
}
|
||||
for tile in &surface.tiles {
|
||||
if let Some((src_rect, dst_rect)) = tile.composite_rects(surface, position, clip_rect) {
|
||||
if let Some((src_rect, dst_rect)) = tile.composite_rects(surface, transform, clip_rect) {
|
||||
draw_tile.draw(&viewport, &dst_rect, &src_rect, surface, tile);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
|
||||
use api::{ColorF, YuvColorSpace, YuvFormat, ImageRendering};
|
||||
use api::units::{DeviceRect, DeviceIntSize, DeviceIntRect, DeviceIntPoint, WorldRect};
|
||||
use api::units::{DevicePixelScale, DevicePoint, PictureRect, TexelRect};
|
||||
use api::units::{DevicePixelScale, DevicePoint, PictureRect, TexelRect, DevicePixel};
|
||||
use crate::batch::{resolve_image, get_buffer_kind};
|
||||
use euclid::Transform3D;
|
||||
use crate::gpu_cache::GpuCache;
|
||||
use crate::gpu_types::{ZBufferId, ZBufferIdGenerator};
|
||||
use crate::internal_types::TextureSource;
|
||||
|
@ -106,10 +107,10 @@ pub enum ExternalSurfaceDependency {
|
|||
/// this will also support RGBA images.
|
||||
pub struct ExternalSurfaceDescriptor {
|
||||
pub local_rect: PictureRect,
|
||||
pub world_rect: WorldRect,
|
||||
pub device_rect: DeviceRect,
|
||||
pub local_clip_rect: PictureRect,
|
||||
pub clip_rect: DeviceRect,
|
||||
pub transform: CompositorSurfaceTransform,
|
||||
pub image_rendering: ImageRendering,
|
||||
pub z_id: ZBufferId,
|
||||
pub dependency: ExternalSurfaceDependency,
|
||||
|
@ -268,6 +269,15 @@ impl CompositorKind {
|
|||
CompositorKind::Native { virtual_surface_size, .. } => *virtual_surface_size,
|
||||
}
|
||||
}
|
||||
|
||||
// We currently only support transforms for Native compositors,
|
||||
// bug 1655639 is filed for adding support to Draw.
|
||||
pub fn supports_transforms(&self) -> bool {
|
||||
match self {
|
||||
CompositorKind::Draw { .. } => false,
|
||||
CompositorKind::Native { .. } => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The backing surface kind for a tile. Same as `TileSurface`, minus
|
||||
|
@ -311,6 +321,7 @@ pub struct CompositeSurfaceDescriptor {
|
|||
pub surface_id: Option<NativeSurfaceId>,
|
||||
pub offset: DevicePoint,
|
||||
pub clip_rect: DeviceRect,
|
||||
pub transform: CompositorSurfaceTransform,
|
||||
// A list of image keys and generations that this compositor surface
|
||||
// depends on. This avoids composites being skipped when the only
|
||||
// thing that has changed is the generation of an compositor surface
|
||||
|
@ -553,6 +564,9 @@ impl CompositeState {
|
|||
surface_id: tile_cache.native_surface.as_ref().map(|s| s.opaque),
|
||||
offset: tile_cache.device_position,
|
||||
clip_rect: device_clip_rect,
|
||||
transform: CompositorSurfaceTransform::create_translation(tile_cache.device_position.x,
|
||||
tile_cache.device_position.y,
|
||||
0.0),
|
||||
image_dependencies: [ImageDependency::INVALID; 3],
|
||||
tile_descriptors: opaque_tile_descriptors,
|
||||
}
|
||||
|
@ -670,11 +684,13 @@ impl CompositeState {
|
|||
|
||||
let image_buffer_kind = get_buffer_kind(planes[0].texture);
|
||||
|
||||
// Only propagate flip_y if the compositor doesn't support transforms,
|
||||
// since otherwise it'll be handled as part of the transform.
|
||||
self.external_surfaces.push(ResolvedExternalSurface {
|
||||
color_data: ResolvedExternalSurfaceColorData::Rgb {
|
||||
image_dependency: image_dependencies[0],
|
||||
plane: planes[0],
|
||||
flip_y,
|
||||
flip_y: flip_y && !self.compositor_kind.supports_transforms(),
|
||||
},
|
||||
image_buffer_kind,
|
||||
update_params,
|
||||
|
@ -682,12 +698,19 @@ impl CompositeState {
|
|||
},
|
||||
}
|
||||
|
||||
// Just use the device_rect for the tile's clip, since we'll clip
|
||||
// in the compositor instead.
|
||||
let tile_clip = if self.compositor_kind.supports_transforms() {
|
||||
external_surface.device_rect
|
||||
} else {
|
||||
clip_rect
|
||||
};
|
||||
let tile = CompositeTile {
|
||||
surface,
|
||||
rect: external_surface.device_rect,
|
||||
valid_rect: external_surface.device_rect.translate(-external_surface.device_rect.origin.to_vector()),
|
||||
dirty_rect: external_surface.device_rect.translate(-external_surface.device_rect.origin.to_vector()),
|
||||
clip_rect,
|
||||
clip_rect: tile_clip,
|
||||
z_id: external_surface.z_id,
|
||||
};
|
||||
|
||||
|
@ -698,7 +721,8 @@ impl CompositeState {
|
|||
CompositeSurfaceDescriptor {
|
||||
surface_id: external_surface.native_surface_id,
|
||||
offset: tile.rect.origin,
|
||||
clip_rect: tile.clip_rect,
|
||||
clip_rect,
|
||||
transform: external_surface.transform,
|
||||
image_dependencies: image_dependencies,
|
||||
tile_descriptors: Vec::new(),
|
||||
}
|
||||
|
@ -714,6 +738,9 @@ impl CompositeState {
|
|||
surface_id: tile_cache.native_surface.as_ref().map(|s| s.alpha),
|
||||
offset: tile_cache.device_position,
|
||||
clip_rect: device_clip_rect,
|
||||
transform: CompositorSurfaceTransform::create_translation(tile_cache.device_position.x,
|
||||
tile_cache.device_position.y,
|
||||
0.0),
|
||||
image_dependencies: [ImageDependency::INVALID; 3],
|
||||
tile_descriptors: alpha_tile_descriptors,
|
||||
}
|
||||
|
@ -810,6 +837,10 @@ pub struct CompositorCapabilities {
|
|||
pub virtual_surface_size: i32,
|
||||
}
|
||||
|
||||
/// The transform type to apply to Compositor surfaces.
|
||||
pub struct CompositorSurfacePixel;
|
||||
pub type CompositorSurfaceTransform = Transform3D<f32, CompositorSurfacePixel, DevicePixel>;
|
||||
|
||||
/// Defines an interface to a native (OS level) compositor. If supplied
|
||||
/// by the client application, then picture cache slices will be
|
||||
/// composited by the OS compositor, rather than drawn via WR batches.
|
||||
|
@ -891,11 +922,10 @@ pub trait Compositor {
|
|||
// We might need to change the interface to maintain a visual
|
||||
// tree that can be mutated?
|
||||
// TODO(gw): We might need to add a concept of a hierachy in future.
|
||||
// TODO(gw): In future, expand to support a more complete transform matrix.
|
||||
fn add_surface(
|
||||
&mut self,
|
||||
id: NativeSurfaceId,
|
||||
position: DeviceIntPoint,
|
||||
transform: CompositorSurfaceTransform,
|
||||
clip_rect: DeviceIntRect,
|
||||
);
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@ extern crate webrender_build;
|
|||
|
||||
#[doc(hidden)]
|
||||
pub use crate::composite::{CompositorConfig, Compositor, CompositorCapabilities};
|
||||
pub use crate::composite::{NativeSurfaceId, NativeTileId, NativeSurfaceInfo};
|
||||
pub use crate::composite::{NativeSurfaceId, NativeTileId, NativeSurfaceInfo, CompositorSurfaceTransform};
|
||||
pub use crate::device::{UploadMethod, VertexUsageHint, get_gl_target, get_unoptimized_shader_source};
|
||||
pub use crate::device::{ProgramBinary, ProgramCache, ProgramCacheObserver, FormatDesc};
|
||||
pub use crate::device::Device;
|
||||
|
|
|
@ -107,7 +107,7 @@ use crate::spatial_tree::{ROOT_SPATIAL_NODE_INDEX,
|
|||
use crate::composite::{CompositorKind, CompositeState, NativeSurfaceId, NativeTileId};
|
||||
use crate::composite::{ExternalSurfaceDescriptor, ExternalSurfaceDependency};
|
||||
use crate::debug_colors;
|
||||
use euclid::{vec2, vec3, Point2D, Scale, Size2D, Vector2D, Rect, Transform3D, SideOffsets2D};
|
||||
use euclid::{vec2, vec3, Point2D, Scale, Size2D, Vector2D, Vector3D, Rect, Transform3D, SideOffsets2D};
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use crate::filterdata::SFilterData;
|
||||
use crate::intern::ItemUid;
|
||||
|
@ -2947,6 +2947,8 @@ impl TileCacheInstance {
|
|||
&mut self,
|
||||
prim_info: &mut PrimitiveDependencyInfo,
|
||||
prim_rect: PictureRect,
|
||||
local_prim_rect: LayoutRect,
|
||||
prim_spatial_node_index: SpatialNodeIndex,
|
||||
frame_context: &FrameVisibilityContext,
|
||||
image_dependencies: &[ImageDependency;3],
|
||||
api_keys: &[ImageKey; 3],
|
||||
|
@ -2960,6 +2962,8 @@ impl TileCacheInstance {
|
|||
self.setup_compositor_surfaces_impl(
|
||||
prim_info,
|
||||
prim_rect,
|
||||
local_prim_rect,
|
||||
prim_spatial_node_index,
|
||||
frame_context,
|
||||
ExternalSurfaceDependency::Yuv {
|
||||
image_dependencies: *image_dependencies,
|
||||
|
@ -2978,6 +2982,8 @@ impl TileCacheInstance {
|
|||
&mut self,
|
||||
prim_info: &mut PrimitiveDependencyInfo,
|
||||
prim_rect: PictureRect,
|
||||
local_prim_rect: LayoutRect,
|
||||
prim_spatial_node_index: SpatialNodeIndex,
|
||||
frame_context: &FrameVisibilityContext,
|
||||
image_dependency: ImageDependency,
|
||||
api_key: ImageKey,
|
||||
|
@ -2991,6 +2997,8 @@ impl TileCacheInstance {
|
|||
self.setup_compositor_surfaces_impl(
|
||||
prim_info,
|
||||
prim_rect,
|
||||
local_prim_rect,
|
||||
prim_spatial_node_index,
|
||||
frame_context,
|
||||
ExternalSurfaceDependency::Rgb {
|
||||
image_dependency,
|
||||
|
@ -3009,6 +3017,8 @@ impl TileCacheInstance {
|
|||
&mut self,
|
||||
prim_info: &mut PrimitiveDependencyInfo,
|
||||
prim_rect: PictureRect,
|
||||
local_prim_rect: LayoutRect,
|
||||
prim_spatial_node_index: SpatialNodeIndex,
|
||||
frame_context: &FrameVisibilityContext,
|
||||
dependency: ExternalSurfaceDependency,
|
||||
api_keys: &[ImageKey; 3],
|
||||
|
@ -3025,9 +3035,6 @@ impl TileCacheInstance {
|
|||
frame_context.spatial_tree,
|
||||
);
|
||||
|
||||
let world_rect = pic_to_world_mapper
|
||||
.map(&prim_rect)
|
||||
.expect("bug: unable to map the primitive to world space");
|
||||
let world_clip_rect = pic_to_world_mapper
|
||||
.map(&prim_info.prim_clip_box.to_rect())
|
||||
.expect("bug: unable to map clip to world space");
|
||||
|
@ -3040,7 +3047,33 @@ impl TileCacheInstance {
|
|||
// TODO(gw): Is there any case where if the primitive ends up on a fractional
|
||||
// boundary we want to _skip_ promoting to a compositor surface and
|
||||
// draw it as part of the content?
|
||||
let device_rect = (world_rect * frame_context.global_device_pixel_scale).round();
|
||||
let (device_rect, transform) = match composite_state.compositor_kind {
|
||||
CompositorKind::Draw { .. } => {
|
||||
let world_rect = pic_to_world_mapper
|
||||
.map(&prim_rect)
|
||||
.expect("bug: unable to map the primitive to world space");
|
||||
let device_rect = (world_rect * frame_context.global_device_pixel_scale).round();
|
||||
|
||||
(device_rect, Transform3D::identity())
|
||||
}
|
||||
CompositorKind::Native { .. } => {
|
||||
// If we have a Native Compositor, then we can support doing the transformation
|
||||
// as part of compositing. Use the local prim rect for the external surface, and
|
||||
// compute the full local to device transform to provide to the compositor.
|
||||
let surface_to_world_mapper : SpaceMapper<PicturePixel, WorldPixel> = SpaceMapper::new_with_target(
|
||||
ROOT_SPATIAL_NODE_INDEX,
|
||||
prim_spatial_node_index,
|
||||
frame_context.global_screen_world_rect,
|
||||
frame_context.spatial_tree,
|
||||
);
|
||||
let prim_origin = Vector3D::new(local_prim_rect.origin.x, local_prim_rect.origin.y, 0.0);
|
||||
let world_to_device_scale = Transform3D::from_scale(frame_context.global_device_pixel_scale);
|
||||
let transform = surface_to_world_mapper.get_transform().pre_translate(prim_origin).post_transform(&world_to_device_scale);
|
||||
|
||||
(local_prim_rect.cast_unit(), transform)
|
||||
}
|
||||
};
|
||||
|
||||
let clip_rect = (world_clip_rect * frame_context.global_device_pixel_scale).round();
|
||||
|
||||
if device_rect.size.width >= MAX_COMPOSITOR_SURFACES_SIZE ||
|
||||
|
@ -3121,12 +3154,12 @@ impl TileCacheInstance {
|
|||
// Each compositor surface allocates a unique z-id
|
||||
self.external_surfaces.push(ExternalSurfaceDescriptor {
|
||||
local_rect: prim_info.prim_clip_box.to_rect(),
|
||||
world_rect,
|
||||
local_clip_rect: prim_info.prim_clip_box.to_rect(),
|
||||
dependency,
|
||||
image_rendering,
|
||||
device_rect,
|
||||
clip_rect,
|
||||
transform: transform.cast_unit(),
|
||||
z_id: composite_state.z_generator.next(),
|
||||
native_surface_id,
|
||||
update_params,
|
||||
|
@ -3338,6 +3371,8 @@ impl TileCacheInstance {
|
|||
promote_to_surface = self.setup_compositor_surfaces_rgb(
|
||||
&mut prim_info,
|
||||
prim_rect,
|
||||
local_prim_rect,
|
||||
prim_spatial_node_index,
|
||||
frame_context,
|
||||
ImageDependency {
|
||||
key: image_data.key,
|
||||
|
@ -3402,6 +3437,8 @@ impl TileCacheInstance {
|
|||
promote_to_surface = self.setup_compositor_surfaces_yuv(
|
||||
&mut prim_info,
|
||||
prim_rect,
|
||||
local_prim_rect,
|
||||
prim_spatial_node_index,
|
||||
frame_context,
|
||||
&image_dependencies,
|
||||
&prim_data.kind.yuv_key,
|
||||
|
|
|
@ -49,7 +49,7 @@ use core::time::Duration;
|
|||
use crate::batch::{AlphaBatchContainer, BatchKind, BatchFeatures, BatchTextures, BrushBatchKind, ClipBatchList};
|
||||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
use crate::capture::{CaptureConfig, ExternalCaptureImage, PlainExternalImage};
|
||||
use crate::composite::{CompositeState, CompositeTileSurface, CompositeTile, ResolvedExternalSurface};
|
||||
use crate::composite::{CompositeState, CompositeTileSurface, CompositeTile, ResolvedExternalSurface, CompositorSurfaceTransform};
|
||||
use crate::composite::{CompositorKind, Compositor, NativeTileId, CompositeSurfaceFormat, ResolvedExternalSurfaceColorData};
|
||||
use crate::composite::{CompositorConfig, NativeSurfaceOperationDetails, NativeSurfaceId, NativeSurfaceOperation};
|
||||
use crate::c_str;
|
||||
|
@ -3374,7 +3374,7 @@ impl Renderer {
|
|||
|
||||
compositor.add_surface(
|
||||
NativeSurfaceId::DEBUG_OVERLAY,
|
||||
DeviceIntPoint::zero(),
|
||||
CompositorSurfaceTransform::identity(),
|
||||
DeviceIntRect::new(
|
||||
DeviceIntPoint::zero(),
|
||||
self.debug_overlay_state.current_size.unwrap(),
|
||||
|
@ -4726,7 +4726,6 @@ impl Renderer {
|
|||
uv_rect.uv0.y = uv_rect.uv1.y;
|
||||
uv_rect.uv1.y = y;
|
||||
}
|
||||
|
||||
let instance = CompositeInstance::new_rgb(
|
||||
surface_rect.to_f32(),
|
||||
surface_rect.to_f32(),
|
||||
|
@ -7737,7 +7736,7 @@ impl CompositeState {
|
|||
for surface in &self.descriptor.surfaces {
|
||||
compositor.add_surface(
|
||||
surface.surface_id.expect("bug: no native surface allocated"),
|
||||
surface.offset.to_i32(),
|
||||
surface.transform,
|
||||
surface.clip_rect.to_i32(),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -333,6 +333,8 @@ pub trait MatrixHelpers<Src, Dst> {
|
|||
/// Turn Z transformation into identity. This is useful when crossing "flat"
|
||||
/// transform styled stacking contexts upon traversing the coordinate systems.
|
||||
fn flatten_z_output(&mut self);
|
||||
|
||||
fn cast_unit<NewSrc, NewDst>(&self) -> Transform3D<f32, NewSrc, NewDst>;
|
||||
}
|
||||
|
||||
impl<Src, Dst> MatrixHelpers<Src, Dst> for Transform3D<f32, Src, Dst> {
|
||||
|
@ -472,6 +474,13 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> for Transform3D<f32, Src, Dst> {
|
|||
self.m33 = 1.0;
|
||||
self.m43 = 0.0;
|
||||
}
|
||||
|
||||
fn cast_unit<NewSrc, NewDst>(&self) -> Transform3D<f32, NewSrc, NewDst> {
|
||||
Transform3D::row_major(self.m11, self.m12, self.m13, self.m14,
|
||||
self.m21, self.m22, self.m23, self.m24,
|
||||
self.m31, self.m32, self.m33, self.m34,
|
||||
self.m41, self.m42, self.m43, self.m44)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PointHelpers<U>
|
||||
|
|
Загрузка…
Ссылка в новой задаче