Bug 1451761. Only paint the dirty rect. r=mstange draft
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Thu, 05 Apr 2018 13:18:22 -0400
changeset 778018 79201aa0b1b19f0dc0f1ff341a256446db34da29
parent 777821 f1307a26d16715c99a218ce848f09f97f39b8c37
push id105364
push userbmo:jmuizelaar@mozilla.com
push dateThu, 05 Apr 2018 17:28:20 +0000
reviewersmstange
bugs1451761
milestone61.0a1
Bug 1451761. Only paint the dirty rect. r=mstange
gfx/webrender_bindings/Moz2DImageRenderer.cpp
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/src/moz2d_renderer.rs
gfx/webrender_bindings/webrender_ffi_generated.h
--- 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,