Index: android_webview/browser/in_process_view_renderer.cc |
diff --git a/android_webview/browser/in_process_view_renderer.cc b/android_webview/browser/in_process_view_renderer.cc |
index 39614d38ce1393af606cafa4e60e686e277382c2..742d89cbf0d325df9e876b2cee624dc4074a5892 100644 |
--- a/android_webview/browser/in_process_view_renderer.cc |
+++ b/android_webview/browser/in_process_view_renderer.cc |
@@ -423,79 +423,102 @@ bool InProcessViewRenderer::DrawSWInternal(jobject java_canvas, |
web_contents_); |
} |
-// static |
-bool InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded( |
- jobject java_canvas, |
- BrowserViewRenderer::JavaHelper* java_helper, |
- const gfx::Vector2d& scroll_correction, |
- const gfx::Rect& clip, |
- InProcessViewRenderer::RenderMethod render_source, |
- void* owner_key) { |
- TRACE_EVENT0("android_webview", |
- "InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded"); |
- |
- JNIEnv* env = AttachCurrentThread(); |
- ScopedPixelAccess auto_release_pixels(env, java_canvas); |
- AwPixelInfo* pixels = auto_release_pixels.pixels(); |
- SkMatrix matrix; |
- SkBitmap::Config config(SkBitmap::kNo_Config); |
- if (pixels) { |
- switch (pixels->config) { |
- case AwConfig_ARGB_8888: |
- config = SkBitmap::kARGB_8888_Config; |
- break; |
- case AwConfig_RGB_565: |
- config = SkBitmap::kRGB_565_Config; |
- break; |
- } |
+namespace { |
- for (int i = 0; i < 9; i++) { |
- matrix.set(i, pixels->matrix[i]); |
- } |
- // Workaround for http://crbug.com/271096: SW draw only supports |
- // translate & scale transforms. |
- if (matrix.getType() & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) |
- config = SkBitmap::kNo_Config; |
- } |
- |
- if (config == SkBitmap::kNo_Config) { |
- // Render into an auxiliary bitmap if pixel info is not available. |
- ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas); |
- TRACE_EVENT0("android_webview", "RenderToAuxBitmap"); |
- ScopedJavaLocalRef<jobject> jbitmap(java_helper->CreateBitmap( |
- env, clip.width(), clip.height(), jcanvas, owner_key)); |
- if (!jbitmap.obj()) { |
- TRACE_EVENT_INSTANT0("android_webview", |
- "EarlyOut_BitmapAllocFail", |
- TRACE_EVENT_SCOPE_THREAD); |
+struct LayerImportState { |
+ bool SetBitmap(const AwBitmapInfo& info) { |
+ SkBitmap::Config config = |
+ info.config == AwConfig_ARGB_8888 ? SkBitmap::kARGB_8888_Config : |
+ info.config == AwConfig_RGB_565 ? SkBitmap::kRGB_565_Config : |
+ SkBitmap::kNo_Config; |
+ if (config == SkBitmap::kNo_Config) |
return false; |
- } |
+ bitmap.setConfig(config, info.width, info.height, info.row_bytes); |
+ bitmap.setPixels(info.pixels); |
- if (!RasterizeIntoBitmap(env, jbitmap, |
- clip.x() - scroll_correction.x(), |
- clip.y() - scroll_correction.y(), |
- render_source)) { |
- TRACE_EVENT_INSTANT0("android_webview", |
- "EarlyOut_RasterizeFail", |
- TRACE_EVENT_SCOPE_THREAD); |
- return false; |
+ LOG(WARNING) << "JOTH decode: " << info.x << ", " << info.y |
+ << ", " << info.width << ", " << info.height; |
+ return true; |
+ } |
+ SkBitmap bitmap; |
+ bool importing; |
+}; |
+ |
+class LayerImportDevice : public SkDevice { |
+ public: |
+ LayerImportDevice(const LayerImportState* state) |
+ : SkDevice(state->bitmap), |
+ state_(state) { |
+ DCHECK(state_->importing); |
+ } |
+ |
+ SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, |
+ int width, int height, |
+ bool isOpaque, |
+ Usage usage) { |
+ const SkBitmap& bitmap = state_->bitmap; |
+ if (!state_->importing) { |
+ DCHECK(bitmap.empty() && state_->bitmap.isNull()); |
+ return new SkDevice(config, width, height, isOpaque); |
} |
+ DCHECK(usage != SkDevice::kGeneral_Usage); |
+ DCHECK(bitmap.config() == config); |
+ DCHECK(bitmap.width() == width); |
+ DCHECK(bitmap.height() == height); |
+ DCHECK(width == 0 || height == 0 || !bitmap.isNull()); |
+ return new LayerImportDevice(state_); |
+ } |
- java_helper->DrawBitmapIntoCanvas(env, jbitmap, jcanvas, |
- clip.x(), clip.y()); |
- return true; |
+ private: |
+ const LayerImportState* state_; |
+}; |
+ |
+bool RenderDirectToCanvas(JNIEnv* env, |
+ jobject java_canvas, |
+ BrowserViewRenderer::JavaHelper* java_helper, |
+ const gfx::Vector2d& scroll_correction, |
+ InProcessViewRenderer::RenderMethod render_source) { |
+ ScopedPixelAccess auto_release_pixels(env, java_canvas); |
+ AwPixelInfo* pixels = auto_release_pixels.pixels(); |
+ if (!pixels) |
+ return false; |
+ |
+ SkMatrix matrix; |
+ for (int i = 0; i < 9; i++) { |
+ matrix.set(i, pixels->matrix[i]); |
} |
+ // Workarounds for http://crbug.com/271096: SW draw only supports |
+ // translate & scale transforms, and a simple rectangular clip. |
+ if (matrix.getType() & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) |
+ return false; |
+ if (pixels->clip_rect_count > 1) |
+ return false; |
// Draw in a SkCanvas built over the pixel information. |
- SkBitmap bitmap; |
- bitmap.setConfig(config, |
- pixels->width, |
- pixels->height, |
- pixels->row_bytes); |
- bitmap.setPixels(pixels->pixels); |
- SkDevice device(bitmap); |
+ if (pixels->layer_count < 1) |
+ return false; |
+ LayerImportState layer; |
+ layer.importing = true; |
+ if (!layer.SetBitmap(pixels->layers[0])) |
+ return false; |
+ LayerImportDevice device(&layer); |
SkCanvas canvas(&device); |
- canvas.setMatrix(matrix); |
+ |
+ // Iterate over the layers above the root (hence, starting a 1). |
+ for (int i = 1; i < pixels->layer_count; ++i) { |
+ const AwBitmapInfo& bitmap = pixels->layers[i]; |
+ layer.SetBitmap(bitmap); |
+ SkRect rect = SkRect::MakeXYWH(bitmap.x, bitmap.y, |
+ bitmap.width, bitmap.height); |
+ // Use a "dest" xfer so that our shadow-layer stack restore is a no-op. |
+ SkPaint dest_mode; |
+ dest_mode.setXfermodeMode(SkXfermode::kDst_Mode); |
+ canvas.saveLayer(&rect, &dest_mode, SkCanvas::kARGB_NoClipLayer_SaveFlag); |
+ DCHECK(canvas.getTopDevice()->getOrigin() == |
+ SkIPoint::Make(bitmap.x, bitmap.y)); |
+ } |
+ layer.bitmap.reset(); |
+ layer.importing = false; |
if (pixels->clip_rect_count) { |
SkRegion clip; |
@@ -508,13 +531,60 @@ bool InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded( |
} |
canvas.setClipRegion(clip); |
} |
- |
+ canvas.setMatrix(matrix); |
canvas.translate(scroll_correction.x(), |
scroll_correction.y()); |
return render_source.Run(&canvas); |
} |
+} // namespace |
+ |
+bool InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded( |
+ jobject java_canvas, |
+ BrowserViewRenderer::JavaHelper* java_helper, |
+ const gfx::Vector2d& scroll_correction, |
+ const gfx::Rect& clip, |
+ InProcessViewRenderer::RenderMethod render_source, |
+ void* owner_key) { |
+ TRACE_EVENT0("android_webview", |
+ "InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded"); |
+ |
+ JNIEnv* env = AttachCurrentThread(); |
+ if (RenderDirectToCanvas(env, |
+ java_canvas, |
+ java_helper, |
+ scroll_correction, |
+ render_source)) { |
+ return true; |
+ } |
+ // Render into an auxiliary bitmap if pixel info is not available. |
+ ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas); |
+ TRACE_EVENT0("android_webview", "RenderToAuxBitmap"); |
+ ScopedJavaLocalRef<jobject> jbitmap(java_helper->CreateBitmap( |
+ env, clip.width(), clip.height(), jcanvas, owner_key)); |
+ if (!jbitmap.obj()) { |
+ TRACE_EVENT_INSTANT0("android_webview", |
+ "EarlyOut_BitmapAllocFail", |
+ TRACE_EVENT_SCOPE_THREAD); |
+ return false; |
+ } |
+ |
+ if (!RasterizeIntoBitmap(env, jbitmap, |
+ clip.x() - scroll_correction.x(), |
+ clip.y() - scroll_correction.y(), |
+ render_source)) { |
+ TRACE_EVENT_INSTANT0("android_webview", |
+ "EarlyOut_RasterizeFail", |
+ TRACE_EVENT_SCOPE_THREAD); |
+ return false; |
+ } |
+ |
+ java_helper->DrawBitmapIntoCanvas(env, jbitmap, jcanvas, |
+ clip.x(), clip.y()); |
+ return true; |
+} |
+ |
skia::RefPtr<SkPicture> InProcessViewRenderer::CapturePicture(int width, |
int height) { |
TRACE_EVENT0("android_webview", "InProcessViewRenderer::CapturePicture"); |