| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "android_webview/browser/browser_view_renderer_impl.h" | |
| 6 | |
| 7 #include <android/bitmap.h> | |
| 8 | |
| 9 #include "android_webview/browser/in_process_view_renderer.h" | |
| 10 #include "android_webview/common/aw_switches.h" | |
| 11 #include "android_webview/common/renderer_picture_map.h" | |
| 12 #include "android_webview/public/browser/draw_gl.h" | |
| 13 #include "android_webview/public/browser/draw_sw.h" | |
| 14 #include "base/android/jni_android.h" | |
| 15 #include "base/command_line.h" | |
| 16 #include "base/debug/trace_event.h" | |
| 17 #include "base/logging.h" | |
| 18 #include "cc/layers/layer.h" | |
| 19 #include "content/public/browser/android/content_view_core.h" | |
| 20 #include "content/public/browser/render_process_host.h" | |
| 21 #include "content/public/browser/render_view_host.h" | |
| 22 #include "content/public/browser/web_contents.h" | |
| 23 #include "third_party/skia/include/core/SkBitmap.h" | |
| 24 #include "third_party/skia/include/core/SkCanvas.h" | |
| 25 #include "third_party/skia/include/core/SkDevice.h" | |
| 26 #include "third_party/skia/include/core/SkGraphics.h" | |
| 27 #include "ui/gfx/size_conversions.h" | |
| 28 #include "ui/gfx/transform.h" | |
| 29 #include "ui/gfx/vector2d_f.h" | |
| 30 #include "ui/gl/gl_bindings.h" | |
| 31 | |
| 32 using base::android::AttachCurrentThread; | |
| 33 using base::android::JavaRef; | |
| 34 using base::android::ScopedJavaLocalRef; | |
| 35 using content::Compositor; | |
| 36 using content::ContentViewCore; | |
| 37 | |
| 38 namespace android_webview { | |
| 39 | |
| 40 namespace { | |
| 41 | |
| 42 // Provides software rendering functions from the Android glue layer. | |
| 43 // Allows preventing extra copies of data when rendering. | |
| 44 AwDrawSWFunctionTable* g_sw_draw_functions = NULL; | |
| 45 | |
| 46 // Tells if the Skia library versions in Android and Chromium are compatible. | |
| 47 // If they are then it's possible to pass Skia objects like SkPictures to the | |
| 48 // Android glue layer via the SW rendering functions. | |
| 49 // If they are not, then additional copies and rasterizations are required | |
| 50 // as a fallback mechanism, which will have an important performance impact. | |
| 51 bool g_is_skia_version_compatible = false; | |
| 52 | |
| 53 typedef base::Callback<bool(SkCanvas*)> RenderMethod; | |
| 54 | |
| 55 bool RasterizeIntoBitmap(JNIEnv* env, | |
| 56 const JavaRef<jobject>& jbitmap, | |
| 57 int scroll_x, | |
| 58 int scroll_y, | |
| 59 const RenderMethod& renderer) { | |
| 60 DCHECK(jbitmap.obj()); | |
| 61 | |
| 62 AndroidBitmapInfo bitmap_info; | |
| 63 if (AndroidBitmap_getInfo(env, jbitmap.obj(), &bitmap_info) < 0) { | |
| 64 LOG(ERROR) << "Error getting java bitmap info."; | |
| 65 return false; | |
| 66 } | |
| 67 | |
| 68 void* pixels = NULL; | |
| 69 if (AndroidBitmap_lockPixels(env, jbitmap.obj(), &pixels) < 0) { | |
| 70 LOG(ERROR) << "Error locking java bitmap pixels."; | |
| 71 return false; | |
| 72 } | |
| 73 | |
| 74 bool succeeded; | |
| 75 { | |
| 76 SkBitmap bitmap; | |
| 77 bitmap.setConfig(SkBitmap::kARGB_8888_Config, | |
| 78 bitmap_info.width, | |
| 79 bitmap_info.height, | |
| 80 bitmap_info.stride); | |
| 81 bitmap.setPixels(pixels); | |
| 82 | |
| 83 SkDevice device(bitmap); | |
| 84 SkCanvas canvas(&device); | |
| 85 canvas.translate(-scroll_x, -scroll_y); | |
| 86 succeeded = renderer.Run(&canvas); | |
| 87 } | |
| 88 | |
| 89 if (AndroidBitmap_unlockPixels(env, jbitmap.obj()) < 0) { | |
| 90 LOG(ERROR) << "Error unlocking java bitmap pixels."; | |
| 91 return false; | |
| 92 } | |
| 93 | |
| 94 return succeeded; | |
| 95 } | |
| 96 | |
| 97 bool RenderPictureToCanvas(SkPicture* picture, SkCanvas* canvas) { | |
| 98 canvas->drawPicture(*picture); | |
| 99 return true; | |
| 100 } | |
| 101 | |
| 102 const void* kUserDataKey = &kUserDataKey; | |
| 103 | |
| 104 } // namespace | |
| 105 | |
| 106 class BrowserViewRendererImpl::UserData : public content::WebContents::Data { | |
| 107 public: | |
| 108 UserData(BrowserViewRendererImpl* ptr) : instance_(ptr) {} | |
| 109 virtual ~UserData() { | |
| 110 instance_->WebContentsGone(); | |
| 111 } | |
| 112 | |
| 113 static BrowserViewRendererImpl* GetInstance(content::WebContents* contents) { | |
| 114 if (!contents) | |
| 115 return NULL; | |
| 116 UserData* data = reinterpret_cast<UserData*>( | |
| 117 contents->GetUserData(kUserDataKey)); | |
| 118 return data ? data->instance_ : NULL; | |
| 119 } | |
| 120 | |
| 121 private: | |
| 122 BrowserViewRendererImpl* instance_; | |
| 123 }; | |
| 124 | |
| 125 // static | |
| 126 BrowserViewRenderer* BrowserViewRendererImpl::Create( | |
| 127 BrowserViewRenderer::Client* client, | |
| 128 JavaHelper* java_helper) { | |
| 129 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
| 130 switches::kNoMergeUIAndRendererCompositorThreads)) { | |
| 131 return new BrowserViewRendererImpl(client, java_helper); | |
| 132 } | |
| 133 | |
| 134 return new InProcessViewRenderer(client, java_helper); | |
| 135 } | |
| 136 | |
| 137 // static | |
| 138 BrowserViewRendererImpl* BrowserViewRendererImpl::FromWebContents( | |
| 139 content::WebContents* contents) { | |
| 140 return UserData::GetInstance(contents); | |
| 141 } | |
| 142 | |
| 143 BrowserViewRendererImpl::BrowserViewRendererImpl( | |
| 144 BrowserViewRenderer::Client* client, | |
| 145 JavaHelper* java_helper) | |
| 146 : client_(client), | |
| 147 java_helper_(java_helper), | |
| 148 view_renderer_host_(new ViewRendererHost(NULL, this)), | |
| 149 compositor_(Compositor::Create(this)), | |
| 150 view_clip_layer_(cc::Layer::Create()), | |
| 151 transform_layer_(cc::Layer::Create()), | |
| 152 scissor_clip_layer_(cc::Layer::Create()), | |
| 153 view_attached_(false), | |
| 154 view_visible_(false), | |
| 155 compositor_visible_(false), | |
| 156 is_composite_pending_(false), | |
| 157 dpi_scale_(1.0f), | |
| 158 page_scale_(1.0f), | |
| 159 new_picture_enabled_(false), | |
| 160 last_frame_context_(NULL), | |
| 161 web_contents_(NULL), | |
| 162 update_frame_info_callback_( | |
| 163 base::Bind(&BrowserViewRendererImpl::OnFrameInfoUpdated, | |
| 164 base::Unretained(this))), | |
| 165 prevent_client_invalidate_(false) { | |
| 166 | |
| 167 DCHECK(java_helper); | |
| 168 | |
| 169 // Define the view hierarchy. | |
| 170 transform_layer_->AddChild(view_clip_layer_); | |
| 171 scissor_clip_layer_->AddChild(transform_layer_); | |
| 172 compositor_->SetRootLayer(scissor_clip_layer_); | |
| 173 | |
| 174 RendererPictureMap::CreateInstance(); | |
| 175 } | |
| 176 | |
| 177 BrowserViewRendererImpl::~BrowserViewRendererImpl() { | |
| 178 SetContents(NULL); | |
| 179 } | |
| 180 | |
| 181 // static | |
| 182 void BrowserViewRenderer::SetAwDrawSWFunctionTable( | |
| 183 AwDrawSWFunctionTable* table) { | |
| 184 g_sw_draw_functions = table; | |
| 185 g_is_skia_version_compatible = | |
| 186 g_sw_draw_functions->is_skia_version_compatible(&SkGraphics::GetVersion); | |
| 187 LOG_IF(WARNING, !g_is_skia_version_compatible) | |
| 188 << "Skia versions are not compatible, rendering performance will suffer."; | |
| 189 } | |
| 190 | |
| 191 // static | |
| 192 AwDrawSWFunctionTable* BrowserViewRenderer::GetAwDrawSWFunctionTable() { | |
| 193 return g_sw_draw_functions; | |
| 194 } | |
| 195 | |
| 196 // static | |
| 197 bool BrowserViewRenderer::IsSkiaVersionCompatible() { | |
| 198 DCHECK(g_sw_draw_functions); | |
| 199 return g_is_skia_version_compatible; | |
| 200 } | |
| 201 | |
| 202 void BrowserViewRendererImpl::SetContents(ContentViewCore* content_view_core) { | |
| 203 // First remove association from the prior ContentViewCore / WebContents. | |
| 204 if (web_contents_) { | |
| 205 ContentViewCore* previous_content_view_core = | |
| 206 ContentViewCore::FromWebContents(web_contents_); | |
| 207 if (previous_content_view_core) { | |
| 208 previous_content_view_core->RemoveFrameInfoCallback( | |
| 209 update_frame_info_callback_); | |
| 210 } | |
| 211 web_contents_->SetUserData(kUserDataKey, NULL); | |
| 212 DCHECK(!web_contents_); // WebContentsGone should have been called. | |
| 213 } | |
| 214 | |
| 215 if (!content_view_core) | |
| 216 return; | |
| 217 | |
| 218 web_contents_ = content_view_core->GetWebContents(); | |
| 219 web_contents_->SetUserData(kUserDataKey, new UserData(this)); | |
| 220 view_renderer_host_->Observe(web_contents_); | |
| 221 | |
| 222 content_view_core->AddFrameInfoCallback(update_frame_info_callback_); | |
| 223 dpi_scale_ = content_view_core->GetDpiScale(); | |
| 224 | |
| 225 view_clip_layer_->RemoveAllChildren(); | |
| 226 view_clip_layer_->AddChild(content_view_core->GetLayer()); | |
| 227 Invalidate(); | |
| 228 } | |
| 229 | |
| 230 void BrowserViewRendererImpl::WebContentsGone() { | |
| 231 web_contents_ = NULL; | |
| 232 } | |
| 233 | |
| 234 bool BrowserViewRendererImpl::PrepareDrawGL(int x, int y) { | |
| 235 hw_rendering_scroll_ = gfx::Point(x, y); | |
| 236 return true; | |
| 237 } | |
| 238 | |
| 239 void BrowserViewRendererImpl::DrawGL(AwDrawGLInfo* draw_info) { | |
| 240 TRACE_EVENT0("android_webview", "BrowserViewRendererImpl::DrawGL"); | |
| 241 | |
| 242 if (view_size_.IsEmpty() || !scissor_clip_layer_ || | |
| 243 draw_info->mode == AwDrawGLInfo::kModeProcess) | |
| 244 return; | |
| 245 | |
| 246 DCHECK_EQ(draw_info->mode, AwDrawGLInfo::kModeDraw); | |
| 247 | |
| 248 SetCompositorVisibility(view_visible_); | |
| 249 if (!compositor_visible_) | |
| 250 return; | |
| 251 | |
| 252 // We need to watch if the current Android context has changed and enforce | |
| 253 // a clean-up in the compositor. | |
| 254 EGLContext current_context = eglGetCurrentContext(); | |
| 255 if (!current_context) { | |
| 256 LOG(WARNING) << "No current context attached. Skipping composite."; | |
| 257 return; | |
| 258 } | |
| 259 | |
| 260 if (last_frame_context_ != current_context) { | |
| 261 if (last_frame_context_) | |
| 262 ResetCompositor(); | |
| 263 last_frame_context_ = current_context; | |
| 264 } | |
| 265 | |
| 266 compositor_->SetWindowBounds(gfx::Size(draw_info->width, draw_info->height)); | |
| 267 | |
| 268 // We need to trigger a compositor invalidate because otherwise, if nothing | |
| 269 // has changed since last draw the compositor will early out (Android may | |
| 270 // trigger a draw at anytime). However, we don't want to trigger a client | |
| 271 // (i.e. Android View system) invalidate as a result of this (otherwise we'll | |
| 272 // end up in a loop of DrawGL calls). | |
| 273 prevent_client_invalidate_ = true; | |
| 274 compositor_->SetNeedsRedraw(); | |
| 275 prevent_client_invalidate_ = false; | |
| 276 | |
| 277 if (draw_info->is_layer) { | |
| 278 // When rendering into a separate layer no view clipping, transform, | |
| 279 // scissoring or background transparency need to be handled. | |
| 280 // The Android framework will composite us afterwards. | |
| 281 compositor_->SetHasTransparentBackground(false); | |
| 282 view_clip_layer_->SetMasksToBounds(false); | |
| 283 transform_layer_->SetTransform(gfx::Transform()); | |
| 284 scissor_clip_layer_->SetMasksToBounds(false); | |
| 285 scissor_clip_layer_->SetPosition(gfx::PointF()); | |
| 286 scissor_clip_layer_->SetBounds(gfx::Size()); | |
| 287 scissor_clip_layer_->SetSublayerTransform(gfx::Transform()); | |
| 288 | |
| 289 } else { | |
| 290 compositor_->SetHasTransparentBackground(true); | |
| 291 | |
| 292 gfx::Rect clip_rect(draw_info->clip_left, draw_info->clip_top, | |
| 293 draw_info->clip_right - draw_info->clip_left, | |
| 294 draw_info->clip_bottom - draw_info->clip_top); | |
| 295 | |
| 296 scissor_clip_layer_->SetPosition(clip_rect.origin()); | |
| 297 scissor_clip_layer_->SetBounds(clip_rect.size()); | |
| 298 scissor_clip_layer_->SetMasksToBounds(true); | |
| 299 | |
| 300 // The compositor clipping architecture enforces us to have the clip layer | |
| 301 // as an ancestor of the area we want to clip, but this makes the transform | |
| 302 // become relative to the clip area rather than the full surface. The clip | |
| 303 // position offset needs to be undone before applying the transform. | |
| 304 gfx::Transform undo_clip_position; | |
| 305 undo_clip_position.Translate(-clip_rect.x(), -clip_rect.y()); | |
| 306 scissor_clip_layer_->SetSublayerTransform(undo_clip_position); | |
| 307 | |
| 308 gfx::Transform transform; | |
| 309 transform.matrix().setColMajorf(draw_info->transform); | |
| 310 | |
| 311 // The scrolling values of the Android Framework affect the transformation | |
| 312 // matrix. This needs to be undone to let the compositor handle scrolling. | |
| 313 // TODO(leandrogracia): when scrolling becomes synchronous we should undo | |
| 314 // or override the translation in the compositor, not the one coming from | |
| 315 // the Android View System, as it could be out of bounds for overscrolling. | |
| 316 transform.Translate(hw_rendering_scroll_.x(), hw_rendering_scroll_.y()); | |
| 317 transform_layer_->SetTransform(transform); | |
| 318 | |
| 319 view_clip_layer_->SetMasksToBounds(true); | |
| 320 } | |
| 321 | |
| 322 compositor_->Composite(); | |
| 323 is_composite_pending_ = false; | |
| 324 | |
| 325 // The GL functor must ensure these are set to zero before returning. | |
| 326 // Not setting them leads to graphical artifacts that can affect other apps. | |
| 327 glBindBuffer(GL_ARRAY_BUFFER, 0); | |
| 328 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); | |
| 329 } | |
| 330 | |
| 331 bool BrowserViewRendererImpl::DrawSW(jobject java_canvas, | |
| 332 const gfx::Rect& clip) { | |
| 333 TRACE_EVENT0("android_webview", "BrowserViewRendererImpl::DrawSW"); | |
| 334 | |
| 335 if (clip.IsEmpty()) | |
| 336 return true; | |
| 337 | |
| 338 AwPixelInfo* pixels; | |
| 339 JNIEnv* env = AttachCurrentThread(); | |
| 340 | |
| 341 // Render into an auxiliary bitmap if pixel info is not available. | |
| 342 if (!g_sw_draw_functions || | |
| 343 (pixels = g_sw_draw_functions->access_pixels(env, java_canvas)) == NULL) { | |
| 344 ScopedJavaLocalRef<jobject> jbitmap(java_helper_->CreateBitmap( | |
| 345 env, clip.width(), clip.height(), true)); | |
| 346 if (!jbitmap.obj()) | |
| 347 return false; | |
| 348 | |
| 349 if (!RasterizeIntoBitmap(env, jbitmap, clip.x(), clip.y(), | |
| 350 base::Bind(&BrowserViewRendererImpl::RenderSW, | |
| 351 base::Unretained(this)))) { | |
| 352 return false; | |
| 353 } | |
| 354 | |
| 355 ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas); | |
| 356 java_helper_->DrawBitmapIntoCanvas(env, jbitmap, jcanvas, | |
| 357 clip.x(), clip.y()); | |
| 358 return true; | |
| 359 } | |
| 360 | |
| 361 // Draw in a SkCanvas built over the pixel information. | |
| 362 bool succeeded = false; | |
| 363 { | |
| 364 SkBitmap bitmap; | |
| 365 bitmap.setConfig(static_cast<SkBitmap::Config>(pixels->config), | |
| 366 pixels->width, | |
| 367 pixels->height, | |
| 368 pixels->row_bytes); | |
| 369 bitmap.setPixels(pixels->pixels); | |
| 370 SkDevice device(bitmap); | |
| 371 SkCanvas canvas(&device); | |
| 372 SkMatrix matrix; | |
| 373 for (int i = 0; i < 9; i++) | |
| 374 matrix.set(i, pixels->matrix[i]); | |
| 375 canvas.setMatrix(matrix); | |
| 376 | |
| 377 SkRegion clip; | |
| 378 if (pixels->clip_region_size) { | |
| 379 size_t bytes_read = clip.readFromMemory(pixels->clip_region); | |
| 380 DCHECK_EQ(pixels->clip_region_size, bytes_read); | |
| 381 canvas.setClipRegion(clip); | |
| 382 } else { | |
| 383 clip.setRect(SkIRect::MakeWH(pixels->width, pixels->height)); | |
| 384 } | |
| 385 | |
| 386 succeeded = RenderSW(&canvas); | |
| 387 } | |
| 388 | |
| 389 g_sw_draw_functions->release_pixels(pixels); | |
| 390 return succeeded; | |
| 391 } | |
| 392 | |
| 393 ScopedJavaLocalRef<jobject> BrowserViewRendererImpl::CapturePicture() { | |
| 394 if (!g_sw_draw_functions) | |
| 395 return ScopedJavaLocalRef<jobject>(); | |
| 396 | |
| 397 gfx::Size record_size = ToCeiledSize(content_size_css_); | |
| 398 | |
| 399 // Return empty Picture objects for empty SkPictures. | |
| 400 JNIEnv* env = AttachCurrentThread(); | |
| 401 if (record_size.width() <= 0 || record_size.height() <= 0) { | |
| 402 return java_helper_->RecordBitmapIntoPicture( | |
| 403 env, ScopedJavaLocalRef<jobject>()); | |
| 404 } | |
| 405 | |
| 406 skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture); | |
| 407 SkCanvas* rec_canvas = picture->beginRecording(record_size.width(), | |
| 408 record_size.height(), | |
| 409 0); | |
| 410 if (!RenderPicture(rec_canvas)) | |
| 411 return ScopedJavaLocalRef<jobject>(); | |
| 412 picture->endRecording(); | |
| 413 | |
| 414 if (g_is_skia_version_compatible) { | |
| 415 // Add a reference that the create_picture() will take ownership of. | |
| 416 picture->ref(); | |
| 417 return ScopedJavaLocalRef<jobject>(env, | |
| 418 g_sw_draw_functions->create_picture(env, picture.get())); | |
| 419 } | |
| 420 | |
| 421 // If Skia versions are not compatible, workaround it by rasterizing the | |
| 422 // picture into a bitmap and drawing it into a new Java picture. | |
| 423 ScopedJavaLocalRef<jobject> jbitmap(java_helper_->CreateBitmap( | |
| 424 env, picture->width(), picture->height(), false)); | |
| 425 if (!jbitmap.obj()) | |
| 426 return ScopedJavaLocalRef<jobject>(); | |
| 427 | |
| 428 if (!RasterizeIntoBitmap(env, jbitmap, 0, 0, | |
| 429 base::Bind(&RenderPictureToCanvas, | |
| 430 base::Unretained(picture.get())))) { | |
| 431 return ScopedJavaLocalRef<jobject>(); | |
| 432 } | |
| 433 | |
| 434 return java_helper_->RecordBitmapIntoPicture(env, jbitmap); | |
| 435 } | |
| 436 | |
| 437 void BrowserViewRendererImpl::EnableOnNewPicture(bool enabled) { | |
| 438 new_picture_enabled_ = enabled; | |
| 439 | |
| 440 // TODO(leandrogracia): when SW rendering uses the compositor rather than | |
| 441 // picture rasterization, send update the renderer side with the correct | |
| 442 // listener state. (For now, we always leave render picture listener enabled). | |
| 443 // render_view_host_ext_->EnableCapturePictureCallback(enabled); | |
| 444 // http://crbug.com/176945 | |
| 445 } | |
| 446 | |
| 447 void BrowserViewRendererImpl::OnVisibilityChanged(bool view_visible, | |
| 448 bool window_visible) { | |
| 449 view_visible_ = window_visible && view_visible; | |
| 450 Invalidate(); | |
| 451 } | |
| 452 | |
| 453 void BrowserViewRendererImpl::OnSizeChanged(int width, int height) { | |
| 454 view_size_ = gfx::Size(width, height); | |
| 455 view_clip_layer_->SetBounds(view_size_); | |
| 456 } | |
| 457 | |
| 458 void BrowserViewRendererImpl::OnAttachedToWindow(int width, int height) { | |
| 459 view_attached_ = true; | |
| 460 view_size_ = gfx::Size(width, height); | |
| 461 view_clip_layer_->SetBounds(view_size_); | |
| 462 } | |
| 463 | |
| 464 void BrowserViewRendererImpl::OnDetachedFromWindow() { | |
| 465 view_attached_ = false; | |
| 466 view_visible_ = false; | |
| 467 SetCompositorVisibility(false); | |
| 468 } | |
| 469 | |
| 470 bool BrowserViewRendererImpl::IsAttachedToWindow() { | |
| 471 return view_attached_; | |
| 472 } | |
| 473 | |
| 474 bool BrowserViewRendererImpl::IsViewVisible() { | |
| 475 return view_visible_; | |
| 476 } | |
| 477 | |
| 478 gfx::Rect BrowserViewRendererImpl::GetScreenRect() { | |
| 479 return gfx::Rect(client_->GetLocationOnScreen(), view_size_); | |
| 480 } | |
| 481 | |
| 482 void BrowserViewRendererImpl::ScheduleComposite() { | |
| 483 TRACE_EVENT0("android_webview", "BrowserViewRendererImpl::ScheduleComposite"); | |
| 484 | |
| 485 if (is_composite_pending_) | |
| 486 return; | |
| 487 | |
| 488 is_composite_pending_ = true; | |
| 489 | |
| 490 if (!prevent_client_invalidate_) | |
| 491 Invalidate(); | |
| 492 } | |
| 493 | |
| 494 skia::RefPtr<SkPicture> BrowserViewRendererImpl::GetLastCapturedPicture() { | |
| 495 // Use the latest available picture if the listener callback is enabled. | |
| 496 skia::RefPtr<SkPicture> picture = | |
| 497 RendererPictureMap::GetInstance()->GetRendererPicture( | |
| 498 web_contents_->GetRoutingID()); | |
| 499 if (picture) return picture; | |
| 500 | |
| 501 // Get it synchronously. | |
| 502 view_renderer_host_->CapturePictureSync(); | |
| 503 return RendererPictureMap::GetInstance()->GetRendererPicture( | |
| 504 web_contents_->GetRoutingID()); | |
| 505 } | |
| 506 | |
| 507 void BrowserViewRendererImpl::OnPictureUpdated(int process_id, | |
| 508 int render_view_id) { | |
| 509 CHECK_EQ(web_contents_->GetRenderProcessHost()->GetID(), process_id); | |
| 510 if (render_view_id != web_contents_->GetRoutingID()) | |
| 511 return; | |
| 512 | |
| 513 client_->OnNewPicture(); | |
| 514 | |
| 515 // TODO(mkosiba): Remove when invalidation path is re-implemented. | |
| 516 Invalidate(); | |
| 517 } | |
| 518 | |
| 519 void BrowserViewRendererImpl::SetCompositorVisibility(bool visible) { | |
| 520 if (compositor_visible_ != visible) { | |
| 521 compositor_visible_ = visible; | |
| 522 compositor_->SetVisible(compositor_visible_); | |
| 523 } | |
| 524 } | |
| 525 | |
| 526 void BrowserViewRendererImpl::ResetCompositor() { | |
| 527 compositor_.reset(content::Compositor::Create(this)); | |
| 528 compositor_->SetRootLayer(scissor_clip_layer_); | |
| 529 } | |
| 530 | |
| 531 void BrowserViewRendererImpl::Invalidate() { | |
| 532 if (view_visible_) | |
| 533 client_->Invalidate(); | |
| 534 } | |
| 535 | |
| 536 bool BrowserViewRendererImpl::RenderSW(SkCanvas* canvas) { | |
| 537 float content_scale = dpi_scale_ * page_scale_; | |
| 538 canvas->scale(content_scale, content_scale); | |
| 539 | |
| 540 // Clear to white any parts of the view not covered by the scaled contents. | |
| 541 // TODO(leandrogracia): this should be automatically done by the SW rendering | |
| 542 // path once multiple layers are supported. | |
| 543 gfx::Size physical_content_size = gfx::ToCeiledSize( | |
| 544 gfx::ScaleSize(content_size_css_, content_scale)); | |
| 545 if (physical_content_size.width() < view_size_.width() || | |
| 546 physical_content_size.height() < view_size_.height()) | |
| 547 canvas->clear(SK_ColorWHITE); | |
| 548 | |
| 549 // TODO(leandrogracia): use the appropriate SW rendering path when available | |
| 550 // instead of abusing CapturePicture. | |
| 551 return RenderPicture(canvas); | |
| 552 } | |
| 553 | |
| 554 bool BrowserViewRendererImpl::RenderPicture(SkCanvas* canvas) { | |
| 555 skia::RefPtr<SkPicture> picture = GetLastCapturedPicture(); | |
| 556 if (!picture) | |
| 557 return false; | |
| 558 | |
| 559 picture->draw(canvas); | |
| 560 return true; | |
| 561 } | |
| 562 | |
| 563 void BrowserViewRendererImpl::OnFrameInfoUpdated( | |
| 564 const gfx::SizeF& content_size, | |
| 565 const gfx::Vector2dF& scroll_offset, | |
| 566 float page_scale_factor) { | |
| 567 page_scale_ = page_scale_factor; | |
| 568 content_size_css_ = content_size; | |
| 569 } | |
| 570 | |
| 571 } // namespace android_webview | |
| OLD | NEW |