Bug 1451761. Only paint the dirty rect. r=mstange
--- a/gfx/webrender_bindings/Moz2DImageRenderer.cpp
+++ b/gfx/webrender_bindings/Moz2DImageRenderer.cpp
@@ -163,16 +163,17 @@ GetUnscaledFont(Translator *aTranslator,
return unscaledFont;
}
static bool Moz2DRenderCallback(const Range<const uint8_t> aBlob,
gfx::IntSize aSize,
gfx::SurfaceFormat aFormat,
const uint16_t *aTileSize,
const mozilla::wr::TileOffset *aTileOffset,
+ const mozilla::wr::DeviceUintRect *aDirtyRect,
Range<uint8_t> aOutput)
{
MOZ_ASSERT(aSize.width > 0 && aSize.height > 0);
if (aSize.width <= 0 || aSize.height <= 0) {
return false;
}
auto stride = aSize.width * gfx::BytesPerPixel(aFormat);
@@ -192,16 +193,21 @@ static bool Moz2DRenderCallback(const Ra
aFormat,
uninitialized
);
if (!dt) {
return false;
}
+ if (aDirtyRect) {
+ Rect dirty(aDirtyRect->origin.x, aDirtyRect->origin.y, aDirtyRect->size.width, aDirtyRect->size.height);
+ dt->PushClipRect(dirty);
+ }
+
if (aTileOffset) {
// It's overkill to use a TiledDrawTarget for a single tile
// but it was the easiest way to get the offset handling working
gfx::TileSet tileset;
gfx::Tile tile;
tile.mDrawTarget = dt;
tile.mTileOrigin = gfx::IntPoint(aTileOffset->x * *aTileSize, aTileOffset->y * *aTileSize);
tileset.mTiles = &tile;
@@ -258,16 +264,28 @@ static bool Moz2DRenderCallback(const Ra
}
Range<const uint8_t> blob(aBlob.begin() + offset, aBlob.begin() + end);
ret = translator.TranslateRecording((char*)blob.begin().get(), blob.length());
MOZ_RELEASE_ASSERT(ret);
offset = extra_end;
}
#if 0
+ dt->SetTransform(gfx::Matrix());
+ float r = float(rand()) / RAND_MAX;
+ float g = float(rand()) / RAND_MAX;
+ float b = float(rand()) / RAND_MAX;
+ dt->FillRect(gfx::Rect(0, 0, aSize.width, aSize.height), gfx::ColorPattern(gfx::Color(r, g, b, 0.5)));
+#endif
+
+ if (aDirtyRect) {
+ dt->PopClip();
+ }
+
+#if 0
static int i = 0;
char filename[40];
sprintf(filename, "out%d.png", i++);
gfxUtils::WriteAsPNG(dt, filename);
#endif
return ret;
}
@@ -277,21 +295,23 @@ static bool Moz2DRenderCallback(const Ra
extern "C" {
bool wr_moz2d_render_cb(const mozilla::wr::ByteSlice blob,
uint32_t width, uint32_t height,
mozilla::wr::ImageFormat aFormat,
const uint16_t *aTileSize,
const mozilla::wr::TileOffset *aTileOffset,
+ const mozilla::wr::DeviceUintRect *aDirtyRect,
mozilla::wr::MutByteSlice output)
{
return mozilla::wr::Moz2DRenderCallback(mozilla::wr::ByteSliceToRange(blob),
mozilla::gfx::IntSize(width, height),
mozilla::wr::ImageFormatToSurfaceFormat(aFormat),
aTileSize,
aTileOffset,
+ aDirtyRect,
mozilla::wr::MutByteSliceToRange(output));
}
} // extern
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -2172,16 +2172,17 @@ pub unsafe extern "C" fn wr_dec_ref_arc(
extern "C" {
// TODO: figure out the API for tiled blob images.
pub fn wr_moz2d_render_cb(blob: ByteSlice,
width: u32,
height: u32,
format: ImageFormat,
tile_size: *const u16,
tile_offset: *const TileOffset,
+ dirty_rect: *const DeviceUintRect,
output: MutByteSlice)
-> bool;
}
type ExternalMessageHandler = unsafe extern "C" fn(msg: *const c_char);
struct WrExternalLogHandler {
error_msg: ExternalMessageHandler,
--- a/gfx/webrender_bindings/src/moz2d_renderer.rs
+++ b/gfx/webrender_bindings/src/moz2d_renderer.rs
@@ -361,17 +361,17 @@ impl BlobImageRenderer for Moz2dImageRen
fn delete(&mut self, key: ImageKey) {
self.blob_commands.remove(&key);
}
fn request(&mut self,
resources: &BlobImageResources,
request: BlobImageRequest,
descriptor: &BlobImageDescriptor,
- _dirty_rect: Option<DeviceUintRect>) {
+ dirty_rect: Option<DeviceUintRect>) {
debug_assert!(!self.rendered_images.contains_key(&request), "{:?}", request);
// TODO: implement tiling.
// Add None in the map of rendered images. This makes it possible to differentiate
// between commands that aren't finished yet (entry in the map is equal to None) and
// keys that have never been requested (entry not in the map), which would cause deadlocks
// if we were to block upon receving their result in resolve!
self.rendered_images.insert(request, None);
@@ -435,16 +435,17 @@ impl BlobImageRenderer for Moz2dImageRen
let result = unsafe {
if wr_moz2d_render_cb(
ByteSlice::new(&commands[..]),
descriptor.width,
descriptor.height,
descriptor.format,
option_to_nullable(&tile_size),
option_to_nullable(&request.tile),
+ option_to_nullable(&dirty_rect),
MutByteSlice::new(output.as_mut_slice())
) {
Ok(RasterizedBlobImage {
width: descriptor.width,
height: descriptor.height,
data: output,
})
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -728,16 +728,18 @@ struct ByteSlice {
bool operator==(const ByteSlice& aOther) const {
return buffer == aOther.buffer &&
len == aOther.len;
}
};
using TileOffset = TypedPoint2D<uint16_t, Tiles>;
+using DeviceUintRect = TypedRect<uint32_t, DevicePixel>;
+
struct MutByteSlice {
uint8_t *buffer;
uintptr_t len;
bool operator==(const MutByteSlice& aOther) const {
return buffer == aOther.buffer &&
len == aOther.len;
}
@@ -904,18 +906,16 @@ struct FontInstancePlatformOptions {
bool operator==(const FontInstancePlatformOptions& aOther) const {
return lcd_filter == aOther.lcd_filter &&
hinting == aOther.hinting;
}
};
#endif
-using DeviceUintRect = TypedRect<uint32_t, DevicePixel>;
-
struct WrOpacityProperty {
uint64_t id;
float opacity;
bool operator==(const WrOpacityProperty& aOther) const {
return id == aOther.id &&
opacity == aOther.opacity;
}
@@ -1339,16 +1339,17 @@ void wr_init_external_log_handler(WrLogL
WR_FUNC;
extern bool wr_moz2d_render_cb(ByteSlice aBlob,
uint32_t aWidth,
uint32_t aHeight,
ImageFormat aFormat,
const uint16_t *aTileSize,
const TileOffset *aTileOffset,
+ const DeviceUintRect *aDirtyRect,
MutByteSlice aOutput);
extern void wr_notifier_external_event(WrWindowId aWindowId,
uintptr_t aRawEvent);
extern void wr_notifier_new_frame_ready(WrWindowId aWindowId);
extern void wr_notifier_new_scroll_frame_ready(WrWindowId aWindowId,