Bug 1646835 - add MapTile/UnmapTile hooks to the WR compositor. r?mstange,gw
Summary:
RenderCompositors for SWGL that wish to provide accelerated compositing need to
subvert the existing Bind/Unbind hooks in the WR compositor. These compositors
need to keep track of their HW tiles without actually binding an OpenGL FBO
for WR to render picture cache tiles. SWGL needs to intervene and get a backing
buffer for tile from the RenderCompositor so that it can create a SWGL FBO for
WR to render the picture cache tile to.
To that end, this adds MapTile/UnmapTile as a replacement for Bind/Unbind for
those scenarios. This is done in a way that it affects only the WrCompositor of
webrender_bindings without actually altering WR's Compositor interface. This is
beneficial because WR does not have to understand the details of SWGL
integration and also so as not to complicate other users of WR such as Servo
who are not currently utilizing SWGL at all.
RenderCompositorOGL is initially modified to use these hooks in this patch. It
later became more convenient to restructure that in a follow-up patch.
Differential Revision:
https://phabricator.services.mozilla.com/D80269
Test Plan:
Reviewers: mstange, gw
Subscribers:
Bug #: 1646835
Differential Diff: PHID-DIFF-hsxc6o5kmmmamde7bfcj
--- a/gfx/webrender_bindings/RenderCompositor.cpp
+++ b/gfx/webrender_bindings/RenderCompositor.cpp
@@ -87,16 +87,29 @@ void wr_compositor_unbind(void* aComposi
compositor->Unbind();
}
void wr_compositor_deinit(void* aCompositor) {
RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor);
compositor->DeInit();
}
+void wr_compositor_map_tile(void* aCompositor, wr::NativeTileId aId,
+ wr::DeviceIntRect aDirtyRect,
+ wr::DeviceIntRect aValidRect, void** aData,
+ int32_t* aStride) {
+ RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor);
+ compositor->MapTile(aId, aDirtyRect, aValidRect, aData, aStride);
+}
+
+void wr_compositor_unmap_tile(void* aCompositor) {
+ RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor);
+ compositor->UnmapTile();
+}
+
/* static */
UniquePtr<RenderCompositor> RenderCompositor::Create(
RefPtr<widget::CompositorWidget>&& aWidget) {
#ifdef XP_WIN
if (gfx::gfxVars::UseWebRenderANGLE()) {
return RenderCompositorANGLE::Create(std::move(aWidget));
}
#endif
--- a/gfx/webrender_bindings/RenderCompositor.h
+++ b/gfx/webrender_bindings/RenderCompositor.h
@@ -95,16 +95,22 @@ class RenderCompositor {
// Interface for wr::Compositor
virtual void CompositorBeginFrame() {}
virtual void CompositorEndFrame() {}
virtual void Bind(wr::NativeTileId aId, wr::DeviceIntPoint* aOffset,
uint32_t* aFboId, wr::DeviceIntRect aDirtyRect,
wr::DeviceIntRect aValidRect) {}
virtual void Unbind() {}
+ virtual bool MapTile(wr::NativeTileId aId, wr::DeviceIntRect aDirtyRect,
+ wr::DeviceIntRect aValidRect, void** aData,
+ int32_t* aStride) {
+ return false;
+ }
+ virtual void UnmapTile() {}
virtual void CreateSurface(wr::NativeSurfaceId aId,
wr::DeviceIntPoint aVirtualOffset,
wr::DeviceIntSize aTileSize, bool aIsOpaque) {}
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,
wr::DeviceIntRect aClipRect) {}
--- a/gfx/webrender_bindings/RenderCompositorOGL.cpp
+++ b/gfx/webrender_bindings/RenderCompositorOGL.cpp
@@ -40,17 +40,16 @@ UniquePtr<RenderCompositor> RenderCompos
RenderCompositorOGL::RenderCompositorOGL(
RefPtr<gl::GLContext>&& aGL, RefPtr<widget::CompositorWidget>&& aWidget)
: RenderCompositor(std::move(aWidget)),
mGL(aGL),
mNativeLayerRoot(GetWidget()->GetNativeLayerRoot()),
mPreviousFrameDoneSync(nullptr),
mThisFrameDoneSync(nullptr) {
- MOZ_ASSERT(mGL);
if (mNativeLayerRoot) {
#ifdef XP_MACOSX
auto pool = RenderThread::Get()->SharedSurfacePool();
if (pool) {
mSurfacePoolHandle = pool->GetHandleForGL(mGL);
}
#endif
MOZ_RELEASE_ASSERT(mSurfacePoolHandle);
@@ -60,17 +59,17 @@ RenderCompositorOGL::RenderCompositorOGL
RenderCompositorOGL::~RenderCompositorOGL() {
if (mNativeLayerRoot) {
mNativeLayerRoot->SetLayers({});
mNativeLayerForEntireWindow = nullptr;
mNativeLayerRootSnapshotter = nullptr;
mNativeLayerRoot = nullptr;
}
- if (!mGL->MakeCurrent()) {
+ if (mGL && !mGL->MakeCurrent()) {
gfxCriticalNote
<< "Failed to make render context current during destroying.";
// Leak resources!
mPreviousFrameDoneSync = nullptr;
mThisFrameDoneSync = nullptr;
return;
}
@@ -78,17 +77,17 @@ RenderCompositorOGL::~RenderCompositorOG
mGL->fDeleteSync(mPreviousFrameDoneSync);
}
if (mThisFrameDoneSync) {
mGL->fDeleteSync(mThisFrameDoneSync);
}
}
bool RenderCompositorOGL::BeginFrame() {
- if (!mGL->MakeCurrent()) {
+ if (mGL && !mGL->MakeCurrent()) {
gfxCriticalNote << "Failed to make render context current, can't draw.";
return false;
}
gfx::IntSize bufferSize = GetBufferSize().ToUnknownSize();
if (mNativeLayerRoot && !ShouldUseNativeCompositor()) {
if (mNativeLayerForEntireWindow &&
mNativeLayerForEntireWindow->GetSize() != bufferSize) {
@@ -99,41 +98,55 @@ bool RenderCompositorOGL::BeginFrame() {
mNativeLayerForEntireWindow =
mNativeLayerRoot->CreateLayer(bufferSize, false, mSurfacePoolHandle);
mNativeLayerForEntireWindow->SetSurfaceIsFlipped(true);
mNativeLayerRoot->AppendLayer(mNativeLayerForEntireWindow);
}
}
if (mNativeLayerForEntireWindow) {
gfx::IntRect bounds({}, bufferSize);
- Maybe<GLuint> fbo = mNativeLayerForEntireWindow->NextSurfaceAsFramebuffer(
- bounds, bounds, true);
- if (!fbo) {
+ if (mGL) {
+ Maybe<GLuint> fbo = mNativeLayerForEntireWindow->NextSurfaceAsFramebuffer(
+ bounds, bounds, true);
+ if (!fbo) {
+ return false;
+ }
+ mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, *fbo);
+ } else if (!MapNativeLayer(mNativeLayerForEntireWindow, bounds, bounds)) {
return false;
}
- mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, *fbo);
- } else {
+ } else if (mGL) {
mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mGL->GetDefaultFramebuffer());
}
return true;
}
+void RenderCompositorOGL::CancelFrame() {
+ if (mNativeLayerForEntireWindow && mLayerTarget) {
+ UnmapNativeLayer();
+ }
+}
+
RenderedFrameId RenderCompositorOGL::EndFrame(
const nsTArray<DeviceIntRect>& aDirtyRects) {
RenderedFrameId frameId = GetNextRenderFrameId();
- InsertFrameDoneSync();
- if (!mNativeLayerRoot) {
- mGL->SwapBuffers();
- return frameId;
+ if (mGL) {
+ InsertFrameDoneSync();
+ if (!mNativeLayerRoot) {
+ mGL->SwapBuffers();
+ } else if (mNativeLayerForEntireWindow) {
+ mGL->fFlush();
+ }
+ } else if (mNativeLayerForEntireWindow && mLayerTarget) {
+ UnmapNativeLayer();
}
if (mNativeLayerForEntireWindow) {
- mGL->fFlush();
mNativeLayerForEntireWindow->NotifySurfaceReady();
mNativeLayerRoot->CommitToScreen();
}
return frameId;
}
void RenderCompositorOGL::InsertFrameDoneSync() {
@@ -184,17 +197,19 @@ bool RenderCompositorOGL::MaybeReadback(
if (!mNativeLayerRootSnapshotter) {
mNativeLayerRootSnapshotter = mNativeLayerRoot->CreateSnapshotter();
}
bool success = mNativeLayerRootSnapshotter->ReadbackPixels(
aReadbackSize, gfx::SurfaceFormat::B8G8R8A8, aReadbackBuffer);
// ReadbackPixels might have changed the current context. Make sure mGL is
// current again.
- mGL->MakeCurrent();
+ if (mGL) {
+ mGL->MakeCurrent();
+ }
return success;
}
uint32_t RenderCompositorOGL::GetMaxUpdateRects() {
if (ShouldUseNativeCompositor() &&
StaticPrefs::gfx_webrender_compositor_max_update_rects_AtStartup() > 0) {
return 1;
@@ -231,58 +246,141 @@ void RenderCompositorOGL::CompositorEndF
int((mTotalPixelCount - mAddedPixelCount) * 100 /
windowPixelCount)),
JS::ProfilingCategoryPair::GRAPHICS, mBeginFrameTimeStamp,
TimeStamp::NowUnfuzzed());
}
#endif
mDrawnPixelCount = 0;
+ if (mGL) {
+ mGL->fFlush();
+ }
+
mNativeLayerRoot->SetLayers(mAddedLayers);
- mGL->fFlush();
mNativeLayerRoot->CommitToScreen();
mSurfacePoolHandle->OnEndFrame();
}
-void RenderCompositorOGL::Bind(wr::NativeTileId aId,
- wr::DeviceIntPoint* aOffset, uint32_t* aFboId,
- wr::DeviceIntRect aDirtyRect,
- wr::DeviceIntRect aValidRect) {
+void RenderCompositorOGL::BindNativeLayer(wr::NativeTileId aId,
+ wr::DeviceIntRect aDirtyRect,
+ wr::DeviceIntRect aValidRect) {
MOZ_RELEASE_ASSERT(!mCurrentlyBoundNativeLayer);
auto surfaceCursor = mSurfaces.find(aId.surface_id);
MOZ_RELEASE_ASSERT(surfaceCursor != mSurfaces.end());
Surface& surface = surfaceCursor->second;
auto layerCursor = surface.mNativeLayers.find(TileKey(aId.x, aId.y));
MOZ_RELEASE_ASSERT(layerCursor != surface.mNativeLayers.end());
RefPtr<layers::NativeLayer> layer = layerCursor->second;
+ gfx::IntRect dirtyRect(aDirtyRect.origin.x, aDirtyRect.origin.y,
+ aDirtyRect.size.width, aDirtyRect.size.height);
+
+ mCurrentlyBoundNativeLayer = layer;
+
+ mDrawnPixelCount += dirtyRect.Area();
+}
+
+void RenderCompositorOGL::UnbindNativeLayer() {
+ MOZ_RELEASE_ASSERT(mCurrentlyBoundNativeLayer);
+
+ mCurrentlyBoundNativeLayer->NotifySurfaceReady();
+ mCurrentlyBoundNativeLayer = nullptr;
+}
+
+void RenderCompositorOGL::Bind(wr::NativeTileId aId,
+ wr::DeviceIntPoint* aOffset, uint32_t* aFboId,
+ wr::DeviceIntRect aDirtyRect,
+ wr::DeviceIntRect aValidRect) {
+ BindNativeLayer(aId, aDirtyRect, aValidRect);
+
gfx::IntRect validRect(aValidRect.origin.x, aValidRect.origin.y,
aValidRect.size.width, aValidRect.size.height);
gfx::IntRect dirtyRect(aDirtyRect.origin.x, aDirtyRect.origin.y,
aDirtyRect.size.width, aDirtyRect.size.height);
- Maybe<GLuint> fbo =
- layer->NextSurfaceAsFramebuffer(validRect, dirtyRect, true);
+ Maybe<GLuint> fbo = mCurrentlyBoundNativeLayer->NextSurfaceAsFramebuffer(
+ validRect, dirtyRect, true);
MOZ_RELEASE_ASSERT(fbo); // TODO: make fallible
- mCurrentlyBoundNativeLayer = layer;
*aFboId = *fbo;
*aOffset = wr::DeviceIntPoint{0, 0};
-
- mDrawnPixelCount += dirtyRect.Area();
}
void RenderCompositorOGL::Unbind() {
- MOZ_RELEASE_ASSERT(mCurrentlyBoundNativeLayer);
+ mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
+
+ UnbindNativeLayer();
+}
+
+bool RenderCompositorOGL::MapNativeLayer(layers::NativeLayer* aLayer,
+ const gfx::IntRect& aDirtyRect,
+ const gfx::IntRect& aValidRect) {
+ uint8_t* data = nullptr;
+ gfx::IntSize size;
+ int32_t stride = 0;
+ gfx::SurfaceFormat format = gfx::SurfaceFormat::UNKNOWN;
+ RefPtr<gfx::DrawTarget> dt = aLayer->NextSurfaceAsDrawTarget(
+ aValidRect, gfx::IntRegion(aDirtyRect), gfx::BackendType::SKIA);
+ if (!dt || !dt->LockBits(&data, &size, &stride, &format)) {
+ return false;
+ }
+ MOZ_ASSERT(format == gfx::SurfaceFormat::B8G8R8A8 ||
+ format == gfx::SurfaceFormat::B8G8R8X8);
+ mLayerTarget = std::move(dt);
+ mLayerData = data;
+ mLayerStride = stride;
+ return true;
+}
+
+void RenderCompositorOGL::UnmapNativeLayer() {
+ MOZ_ASSERT(mLayerTarget && mLayerData);
+ mLayerTarget->ReleaseBits(mLayerData);
+ mLayerTarget = nullptr;
+ mLayerData = nullptr;
+ mLayerStride = 0;
+}
- mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
- mCurrentlyBoundNativeLayer->NotifySurfaceReady();
- mCurrentlyBoundNativeLayer = nullptr;
+bool RenderCompositorOGL::GetMappedBuffer(uint8_t** aData, int32_t* aStride) {
+ if (mNativeLayerForEntireWindow && mLayerData) {
+ *aData = mLayerData;
+ *aStride = mLayerStride;
+ return true;
+ }
+ return false;
+}
+
+bool RenderCompositorOGL::MapTile(wr::NativeTileId aId,
+ wr::DeviceIntRect aDirtyRect,
+ wr::DeviceIntRect aValidRect,
+ void** aData, int32_t* aStride) {
+ if (!mNativeLayerRoot || mNativeLayerForEntireWindow) {
+ return false;
+ }
+ BindNativeLayer(aId, aDirtyRect, aValidRect);
+ gfx::IntRect dirtyRect(aDirtyRect.origin.x, aDirtyRect.origin.y,
+ aDirtyRect.size.width, aDirtyRect.size.height);
+ gfx::IntRect validRect(aValidRect.origin.x, aValidRect.origin.y,
+ aValidRect.size.width, aValidRect.size.height);
+ if (!MapNativeLayer(mCurrentlyBoundNativeLayer, dirtyRect, validRect)) {
+ UnbindNativeLayer();
+ return false;
+ }
+ *aData = mLayerData;
+ *aStride = mLayerStride;
+ return true;
+}
+
+void RenderCompositorOGL::UnmapTile() {
+ if (!mNativeLayerForEntireWindow && mCurrentlyBoundNativeLayer) {
+ UnmapNativeLayer();
+ UnbindNativeLayer();
+ }
}
void RenderCompositorOGL::CreateSurface(wr::NativeSurfaceId aId,
wr::DeviceIntPoint aVirtualOffset,
wr::DeviceIntSize aTileSize,
bool aIsOpaque) {
MOZ_RELEASE_ASSERT(mSurfaces.find(aId) == mSurfaces.end());
mSurfaces.insert({aId, Surface{aTileSize, aIsOpaque}});
--- a/gfx/webrender_bindings/RenderCompositorOGL.h
+++ b/gfx/webrender_bindings/RenderCompositorOGL.h
@@ -27,21 +27,24 @@ class RenderCompositorOGL : public Rende
static UniquePtr<RenderCompositor> Create(
RefPtr<widget::CompositorWidget>&& aWidget);
RenderCompositorOGL(RefPtr<gl::GLContext>&& aGL,
RefPtr<widget::CompositorWidget>&& aWidget);
virtual ~RenderCompositorOGL();
bool BeginFrame() override;
+ void CancelFrame() override;
RenderedFrameId EndFrame(const nsTArray<DeviceIntRect>& aDirtyRects) final;
bool WaitForGPU() override;
void Pause() override;
bool Resume() override;
+ bool GetMappedBuffer(uint8_t** aData, int32_t* aStride) override;
+
gl::GLContext* gl() const override { return mGL; }
bool UseANGLE() const override { return false; }
LayoutDeviceIntSize GetBufferSize() override;
bool ShouldUseNativeCompositor() override;
uint32_t GetMaxUpdateRects() override;
@@ -53,16 +56,20 @@ class RenderCompositorOGL : public Rende
// Interface for wr::Compositor
void CompositorBeginFrame() override;
void CompositorEndFrame() override;
void Bind(wr::NativeTileId aId, wr::DeviceIntPoint* aOffset, uint32_t* aFboId,
wr::DeviceIntRect aDirtyRect,
wr::DeviceIntRect aValidRect) override;
void Unbind() override;
+ bool MapTile(wr::NativeTileId aId, wr::DeviceIntRect aDirtyRect,
+ wr::DeviceIntRect aValidRect, void** aData,
+ int32_t* aStride) override;
+ void UnmapTile() override;
void CreateSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aVirtualOffset,
wr::DeviceIntSize aTileSize, bool aIsOpaque) override;
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,
wr::DeviceIntRect aClipRect) override;
CompositorCapabilities GetCompositorCapabilities() override;
@@ -72,16 +79,25 @@ class RenderCompositorOGL : public Rende
int32_t mX;
int32_t mY;
};
protected:
void InsertFrameDoneSync();
+ void BindNativeLayer(wr::NativeTileId aId, wr::DeviceIntRect aDirtyRect,
+ wr::DeviceIntRect aValidRect);
+ void UnbindNativeLayer();
+
+ bool MapNativeLayer(layers::NativeLayer* aLayer,
+ const gfx::IntRect& aDirtyRect,
+ const gfx::IntRect& aValidRect);
+ void UnmapNativeLayer();
+
RefPtr<gl::GLContext> mGL;
// Can be null.
RefPtr<layers::NativeLayerRoot> mNativeLayerRoot;
UniquePtr<layers::NativeLayerRootSnapshotter> mNativeLayerRootSnapshotter;
RefPtr<layers::NativeLayer> mNativeLayerForEntireWindow;
RefPtr<layers::SurfacePoolHandle> mSurfacePoolHandle;
@@ -107,16 +123,19 @@ class RenderCompositorOGL : public Rende
struct SurfaceIdHashFn {
std::size_t operator()(const wr::NativeSurfaceId& aId) const {
return HashGeneric(wr::AsUint64(aId));
}
};
// Used in native compositor mode:
RefPtr<layers::NativeLayer> mCurrentlyBoundNativeLayer;
+ RefPtr<gfx::DrawTarget> mLayerTarget;
+ uint8_t* mLayerData = nullptr;
+ int32_t mLayerStride = 0;
nsTArray<RefPtr<layers::NativeLayer>> mAddedLayers;
uint64_t mTotalPixelCount = 0;
uint64_t mAddedPixelCount = 0;
uint64_t mAddedClippedPixelCount = 0;
uint64_t mDrawnPixelCount = 0;
gfx::IntRect mVisibleBounds;
std::unordered_map<wr::NativeSurfaceId, Surface, SurfaceIdHashFn> mSurfaces;
TimeStamp mBeginFrameTimeStamp;
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1214,16 +1214,25 @@ extern "C" {
id: NativeSurfaceId,
position: DeviceIntPoint,
clip_rect: DeviceIntRect,
);
fn wr_compositor_end_frame(compositor: *mut c_void);
fn wr_compositor_enable_native_compositor(compositor: *mut c_void, enable: bool);
fn wr_compositor_deinit(compositor: *mut c_void);
fn wr_compositor_get_capabilities(compositor: *mut c_void) -> CompositorCapabilities;
+ fn wr_compositor_map_tile(
+ compositor: *mut c_void,
+ id: NativeTileId,
+ dirty_rect: DeviceIntRect,
+ valid_rect: DeviceIntRect,
+ data: &mut *mut c_void,
+ stride: &mut i32,
+ );
+ fn wr_compositor_unmap_tile(compositor: *mut c_void);
}
pub struct WrCompositor(*mut c_void);
impl Compositor for WrCompositor {
fn create_surface(
&mut self,
id: NativeSurfaceId,
@@ -1310,16 +1319,68 @@ impl Compositor for WrCompositor {
}
}
fn get_capabilities(&self) -> CompositorCapabilities {
unsafe { wr_compositor_get_capabilities(self.0) }
}
}
+/// Information about the underlying data buffer of a mapped tile.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct MappedTileInfo {
+ pub data: *mut c_void,
+ pub stride: i32,
+}
+
+/// WrCompositor-specific extensions to the basic Compositor interface.
+impl WrCompositor {
+ /// Map a tile's underlying buffer so it can be used as the backing for
+ /// a SWGL framebuffer. This is intended to be a replacement for 'bind'
+ /// in any compositors that intend to directly interoperate with SWGL
+ /// while supporting some form of native layers.
+ pub fn map_tile(
+ &mut self,
+ id: NativeTileId,
+ dirty_rect: DeviceIntRect,
+ valid_rect: DeviceIntRect,
+ ) -> Option<MappedTileInfo> {
+ let mut tile_info = MappedTileInfo {
+ data: ptr::null_mut(),
+ stride: 0,
+ };
+
+ unsafe {
+ wr_compositor_map_tile(
+ self.0,
+ id,
+ dirty_rect,
+ valid_rect,
+ &mut tile_info.data,
+ &mut tile_info.stride,
+ );
+ }
+
+ if tile_info.data != ptr::null_mut() && tile_info.stride != 0 {
+ Some(tile_info)
+ } else {
+ None
+ }
+ }
+
+ /// Unmap a tile that was was previously mapped via map_tile to signal
+ /// that SWGL is done rendering to the buffer.
+ pub fn unmap_tile(&mut self) {
+ unsafe {
+ wr_compositor_unmap_tile(self.0);
+ }
+ }
+}
+
// Call MakeCurrent before this.
#[no_mangle]
pub extern "C" fn wr_window_new(
window_id: WrWindowId,
window_width: i32,
window_height: i32,
support_low_priority_transactions: bool,
support_low_priority_threadpool: bool,
@@ -1400,18 +1461,18 @@ pub extern "C" fn wr_window_new(
let color = if cfg!(target_os = "android") {
// The color is for avoiding black flash before receiving display list.
ColorF::new(1.0, 1.0, 1.0, 1.0)
} else {
ColorF::new(0.0, 0.0, 0.0, 0.0)
};
let compositor_config = if software {
- let wr_compositor: Option<Box<dyn Compositor>> = if compositor != ptr::null_mut() {
- Some(Box::new(WrCompositor(compositor)))
+ let wr_compositor = if compositor != ptr::null_mut() {
+ Some(WrCompositor(compositor))
} else {
None
};
CompositorConfig::Native {
max_update_rects: 1,
compositor: Box::new(SwCompositor::new(sw_gl.unwrap(), native_gl, wr_compositor)),
}
} else if compositor != ptr::null_mut() {
--- a/gfx/webrender_bindings/src/swgl_bindings.rs
+++ b/gfx/webrender_bindings/src/swgl_bindings.rs
@@ -1,12 +1,13 @@
/* 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/. */
+use bindings::WrCompositor;
use gleam::{gl, gl::Gl};
use std::collections::hash_map::HashMap;
use std::os::raw::c_void;
use std::ptr;
use std::rc::Rc;
use webrender::{api::units::*, Compositor, CompositorCapabilities, NativeSurfaceId, NativeSurfaceInfo, NativeTileId};
#[no_mangle]
@@ -205,25 +206,25 @@ impl DrawTileHelper {
self.gl.use_program(0);
self.gl.bind_vertex_array(0);
}
}
pub struct SwCompositor {
gl: swgl::Context,
native_gl: Option<Rc<dyn gl::Gl>>,
- compositor: Option<Box<dyn Compositor>>,
+ compositor: Option<WrCompositor>,
surfaces: HashMap<NativeSurfaceId, SwSurface>,
frame_surfaces: Vec<(NativeSurfaceId, DeviceIntPoint, DeviceIntRect)>,
cur_tile: NativeTileId,
draw_tile: Option<DrawTileHelper>,
}
impl SwCompositor {
- pub fn new(gl: swgl::Context, native_gl: Option<Rc<dyn gl::Gl>>, compositor: Option<Box<dyn Compositor>>) -> Self {
+ pub fn new(gl: swgl::Context, native_gl: Option<Rc<dyn gl::Gl>>, compositor: Option<WrCompositor>) -> Self {
SwCompositor {
gl,
compositor,
surfaces: HashMap::new(),
frame_surfaces: Vec::new(),
cur_tile: NativeTileId {
surface_id: NativeSurfaceId(0),
x: 0,
@@ -406,39 +407,47 @@ impl Compositor for SwCompositor {
if let Some(surface) = self.surfaces.get_mut(&id.surface_id) {
if let Some(tile) = surface.tiles.iter_mut().find(|t| t.x == id.x && t.y == id.y) {
tile.dirty_rect = dirty_rect;
tile.valid_rect = valid_rect;
if valid_rect.is_empty() {
return surface_info;
}
+ let mut stride = 0;
let mut buf = ptr::null_mut();
- if let Some(native_gl) = &self.native_gl {
+ if let Some(compositor) = &mut self.compositor {
+ if let Some(tile_info) = compositor.map_tile(id, dirty_rect, valid_rect) {
+ stride = tile_info.stride;
+ buf = tile_info.data;
+ }
+ } else if let Some(native_gl) = &self.native_gl {
if tile.pbo_id != 0 {
native_gl.bind_buffer(gl::PIXEL_UNPACK_BUFFER, tile.pbo_id);
buf = native_gl.map_buffer_range(
gl::PIXEL_UNPACK_BUFFER,
0,
valid_rect.size.area() as isize * 4 + 16,
gl::MAP_WRITE_BIT | gl::MAP_INVALIDATE_BUFFER_BIT,
); // | gl::MAP_UNSYNCHRONIZED_BIT);
- if buf == ptr::null_mut() {
+ if buf != ptr::null_mut() {
+ stride = valid_rect.size.width * 4;
+ } else {
native_gl.bind_buffer(gl::PIXEL_UNPACK_BUFFER, 0);
native_gl.delete_buffers(&[tile.pbo_id]);
tile.pbo_id = 0;
}
}
}
self.gl.set_texture_buffer(
tile.color_id,
gl::RGBA8,
valid_rect.size.width,
valid_rect.size.height,
- valid_rect.size.width * 4,
+ stride,
buf,
surface.tile_size.width,
surface.tile_size.height,
);
self.gl.set_texture_buffer(
tile.depth_id,
gl::DEPTH_COMPONENT16,
valid_rect.size.width,
@@ -452,27 +461,33 @@ impl Compositor for SwCompositor {
surface_info.origin -= valid_rect.origin.to_vector();
}
}
surface_info
}
fn unbind(&mut self) {
- let native_gl = match &self.native_gl {
- Some(native_gl) => native_gl,
- None => return,
- };
-
let id = self.cur_tile;
if let Some(surface) = self.surfaces.get_mut(&id.surface_id) {
if let Some(tile) = surface.tiles.iter().find(|t| t.x == id.x && t.y == id.y) {
if tile.valid_rect.is_empty() {
return;
}
+
+ if let Some(compositor) = &mut self.compositor {
+ compositor.unmap_tile();
+ return;
+ }
+
+ let native_gl = match &self.native_gl {
+ Some(native_gl) => native_gl,
+ None => return,
+ };
+
let (swbuf, _, _, stride) = self.gl.get_color_buffer(tile.fbo_id, true);
assert!(stride % 4 == 0);
let buf = if tile.pbo_id != 0 {
native_gl.unmap_buffer(gl::PIXEL_UNPACK_BUFFER);
0 as *mut c_void
} else {
swbuf
};