| 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");
|
|
|