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 #include <sys/system_properties.h> |
| 9 |
| 10 #include "android_webview/common/renderer_picture_map.h" |
| 11 #include "android_webview/public/browser/draw_gl.h" |
| 12 #include "android_webview/public/browser/draw_sw.h" |
| 13 #include "base/android/jni_android.h" |
| 14 #include "base/debug/trace_event.h" |
| 15 #include "base/logging.h" |
| 16 #include "cc/layer.h" |
| 17 #include "content/public/browser/android/content_view_core.h" |
| 18 #include "content/public/browser/render_process_host.h" |
| 19 #include "content/public/browser/web_contents.h" |
| 20 #include "third_party/skia/include/core/SkBitmap.h" |
| 21 #include "third_party/skia/include/core/SkCanvas.h" |
| 22 #include "third_party/skia/include/core/SkDevice.h" |
| 23 #include "third_party/skia/include/core/SkGraphics.h" |
| 24 #include "ui/gfx/size.h" |
| 25 #include "ui/gfx/transform.h" |
| 26 #include "ui/gl/gl_bindings.h" |
| 27 |
| 28 // TODO(leandrogracia): remove when crbug.com/164140 is closed. |
| 29 // Borrowed from gl2ext.h. Cannot be included due to conflicts with |
| 30 // gl_bindings.h and the EGL library methods (eglGetCurrentContext). |
| 31 #ifndef GL_TEXTURE_EXTERNAL_OES |
| 32 #define GL_TEXTURE_EXTERNAL_OES 0x8D65 |
| 33 #endif |
| 34 |
| 35 #ifndef GL_TEXTURE_BINDING_EXTERNAL_OES |
| 36 #define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67 |
| 37 #endif |
| 38 |
| 39 using base::android::AttachCurrentThread; |
| 40 using base::android::JavaRef; |
| 41 using base::android::ScopedJavaLocalRef; |
| 42 using content::Compositor; |
| 43 using content::ContentViewCore; |
| 44 |
| 45 namespace { |
| 46 |
| 47 // Provides software rendering functions from the Android glue layer. |
| 48 // Allows preventing extra copies of data when rendering. |
| 49 AwDrawSWFunctionTable* g_sw_draw_functions = NULL; |
| 50 |
| 51 // Tells if the Skia library versions in Android and Chromium are compatible. |
| 52 // If they are then it's possible to pass Skia objects like SkPictures to the |
| 53 // Android glue layer via the SW rendering functions. |
| 54 // If they are not, then additional copies and rasterizations are required |
| 55 // as a fallback mechanism, which will have an important performance impact. |
| 56 bool g_is_skia_version_compatible = false; |
| 57 |
| 58 typedef base::Callback<bool(SkCanvas*)> RenderMethod; |
| 59 |
| 60 static bool RasterizeIntoBitmap(JNIEnv* env, |
| 61 const JavaRef<jobject>& jbitmap, |
| 62 int scroll_x, |
| 63 int scroll_y, |
| 64 const RenderMethod& renderer) { |
| 65 DCHECK(jbitmap.obj()); |
| 66 |
| 67 AndroidBitmapInfo bitmap_info; |
| 68 if (AndroidBitmap_getInfo(env, jbitmap.obj(), &bitmap_info) < 0) { |
| 69 LOG(ERROR) << "Error getting java bitmap info."; |
| 70 return false; |
| 71 } |
| 72 |
| 73 void* pixels = NULL; |
| 74 if (AndroidBitmap_lockPixels(env, jbitmap.obj(), &pixels) < 0) { |
| 75 LOG(ERROR) << "Error locking java bitmap pixels."; |
| 76 return false; |
| 77 } |
| 78 |
| 79 bool succeeded; |
| 80 { |
| 81 SkBitmap bitmap; |
| 82 bitmap.setConfig(SkBitmap::kARGB_8888_Config, |
| 83 bitmap_info.width, |
| 84 bitmap_info.height, |
| 85 bitmap_info.stride); |
| 86 bitmap.setPixels(pixels); |
| 87 |
| 88 SkDevice device(bitmap); |
| 89 SkCanvas canvas(&device); |
| 90 canvas.translate(-scroll_x, -scroll_y); |
| 91 succeeded = renderer.Run(&canvas); |
| 92 } |
| 93 |
| 94 if (AndroidBitmap_unlockPixels(env, jbitmap.obj()) < 0) { |
| 95 LOG(ERROR) << "Error unlocking java bitmap pixels."; |
| 96 return false; |
| 97 } |
| 98 |
| 99 return succeeded; |
| 100 } |
| 101 |
| 102 } // namespace |
| 103 |
| 104 namespace android_webview { |
| 105 |
| 106 // static |
| 107 BrowserViewRendererImpl* BrowserViewRendererImpl::Create( |
| 108 BrowserViewRenderer::Client* client, |
| 109 JavaHelper* java_helper) { |
| 110 return new BrowserViewRendererImpl(client, java_helper); |
| 111 } |
| 112 |
| 113 BrowserViewRendererImpl::BrowserViewRendererImpl( |
| 114 BrowserViewRenderer::Client* client, |
| 115 JavaHelper* java_helper) |
| 116 : client_(client), |
| 117 java_helper_(java_helper), |
| 118 ALLOW_THIS_IN_INITIALIZER_LIST(compositor_(Compositor::Create(this))), |
| 119 view_clip_layer_(cc::Layer::create()), |
| 120 transform_layer_(cc::Layer::create()), |
| 121 scissor_clip_layer_(cc::Layer::create()), |
| 122 view_visible_(false), |
| 123 compositor_visible_(false), |
| 124 is_composite_pending_(false), |
| 125 dpi_scale_(1.0f), |
| 126 on_new_picture_mode_(kOnNewPictureDisabled), |
| 127 last_frame_context_(NULL), |
| 128 web_contents_(NULL) { |
| 129 DCHECK(java_helper); |
| 130 |
| 131 // Define the view hierarchy. |
| 132 transform_layer_->addChild(view_clip_layer_); |
| 133 scissor_clip_layer_->addChild(transform_layer_); |
| 134 compositor_->SetRootLayer(scissor_clip_layer_); |
| 135 |
| 136 RendererPictureMap::CreateInstance(); |
| 137 } |
| 138 |
| 139 BrowserViewRendererImpl::~BrowserViewRendererImpl() { |
| 140 } |
| 141 |
| 142 // static |
| 143 void BrowserViewRendererImpl::SetAwDrawSWFunctionTable( |
| 144 AwDrawSWFunctionTable* table) { |
| 145 g_sw_draw_functions = table; |
| 146 g_is_skia_version_compatible = |
| 147 g_sw_draw_functions->is_skia_version_compatible(&SkGraphics::GetVersion); |
| 148 LOG_IF(WARNING, !g_is_skia_version_compatible) |
| 149 << "Skia versions are not compatible, rendering performance will suffer."; |
| 150 } |
| 151 |
| 152 void BrowserViewRendererImpl::SetContents(ContentViewCore* content_view_core) { |
| 153 dpi_scale_ = content_view_core->GetDpiScale(); |
| 154 web_contents_ = content_view_core->GetWebContents(); |
| 155 if (!view_renderer_host_) |
| 156 view_renderer_host_.reset(new ViewRendererHost(web_contents_, this)); |
| 157 else |
| 158 view_renderer_host_->Observe(web_contents_); |
| 159 |
| 160 view_clip_layer_->removeAllChildren(); |
| 161 view_clip_layer_->addChild(content_view_core->GetLayer()); |
| 162 Invalidate(); |
| 163 } |
| 164 |
| 165 void BrowserViewRendererImpl::DrawGL(AwDrawGLInfo* draw_info) { |
| 166 TRACE_EVENT0("android_webview", "BrowserViewRendererImpl::DrawGL"); |
| 167 |
| 168 if (view_size_.IsEmpty() || !scissor_clip_layer_ || |
| 169 draw_info->mode == AwDrawGLInfo::kModeProcess) |
| 170 return; |
| 171 |
| 172 DCHECK_EQ(draw_info->mode, AwDrawGLInfo::kModeDraw); |
| 173 |
| 174 SetCompositorVisibility(view_visible_); |
| 175 if (!compositor_visible_) |
| 176 return; |
| 177 |
| 178 // TODO(leandrogracia): remove when crbug.com/164140 is closed. |
| 179 // --------------------------------------------------------------------------- |
| 180 GLint texture_external_oes_binding; |
| 181 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_external_oes_binding); |
| 182 |
| 183 GLint vertex_array_buffer_binding; |
| 184 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &vertex_array_buffer_binding); |
| 185 |
| 186 GLint index_array_buffer_binding; |
| 187 glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &index_array_buffer_binding); |
| 188 |
| 189 GLint pack_alignment; |
| 190 glGetIntegerv(GL_PACK_ALIGNMENT, &pack_alignment); |
| 191 |
| 192 GLint unpack_alignment; |
| 193 glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment); |
| 194 |
| 195 struct { |
| 196 GLint enabled; |
| 197 GLint size; |
| 198 GLint type; |
| 199 GLint normalized; |
| 200 GLint stride; |
| 201 GLvoid* pointer; |
| 202 } vertex_attrib[3]; |
| 203 |
| 204 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(vertex_attrib); ++i) { |
| 205 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, |
| 206 &vertex_attrib[i].enabled); |
| 207 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, |
| 208 &vertex_attrib[i].size); |
| 209 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, |
| 210 &vertex_attrib[i].type); |
| 211 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, |
| 212 &vertex_attrib[i].normalized); |
| 213 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, |
| 214 &vertex_attrib[i].stride); |
| 215 glGetVertexAttribPointerv(i, GL_VERTEX_ATTRIB_ARRAY_POINTER, |
| 216 &vertex_attrib[i].pointer); |
| 217 } |
| 218 |
| 219 GLboolean depth_test; |
| 220 glGetBooleanv(GL_DEPTH_TEST, &depth_test); |
| 221 |
| 222 GLboolean cull_face; |
| 223 glGetBooleanv(GL_CULL_FACE, &cull_face); |
| 224 |
| 225 GLboolean color_mask[4]; |
| 226 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask); |
| 227 |
| 228 GLboolean blend_enabled; |
| 229 glGetBooleanv(GL_BLEND, &blend_enabled); |
| 230 |
| 231 GLint blend_src_rgb; |
| 232 glGetIntegerv(GL_BLEND_SRC_RGB, &blend_src_rgb); |
| 233 |
| 234 GLint blend_src_alpha; |
| 235 glGetIntegerv(GL_BLEND_SRC_ALPHA, &blend_src_alpha); |
| 236 |
| 237 GLint blend_dest_rgb; |
| 238 glGetIntegerv(GL_BLEND_DST_RGB, &blend_dest_rgb); |
| 239 |
| 240 GLint blend_dest_alpha; |
| 241 glGetIntegerv(GL_BLEND_DST_ALPHA, &blend_dest_alpha); |
| 242 |
| 243 GLint active_texture; |
| 244 glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); |
| 245 |
| 246 GLint viewport[4]; |
| 247 glGetIntegerv(GL_VIEWPORT, viewport); |
| 248 |
| 249 GLboolean scissor_test; |
| 250 glGetBooleanv(GL_SCISSOR_TEST, &scissor_test); |
| 251 |
| 252 GLint scissor_box[4]; |
| 253 glGetIntegerv(GL_SCISSOR_BOX, scissor_box); |
| 254 |
| 255 GLint current_program; |
| 256 glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program); |
| 257 // --------------------------------------------------------------------------- |
| 258 |
| 259 // We need to watch if the current Android context has changed and enforce |
| 260 // a clean-up in the compositor. |
| 261 EGLContext current_context = eglGetCurrentContext(); |
| 262 if (!current_context) { |
| 263 LOG(WARNING) << "No current context attached. Skipping composite."; |
| 264 return; |
| 265 } |
| 266 |
| 267 if (last_frame_context_ != current_context) { |
| 268 if (last_frame_context_) |
| 269 ResetCompositor(); |
| 270 last_frame_context_ = current_context; |
| 271 } |
| 272 |
| 273 compositor_->SetWindowBounds(gfx::Size(draw_info->width, draw_info->height)); |
| 274 |
| 275 if (draw_info->is_layer) { |
| 276 // When rendering into a separate layer no view clipping, transform, |
| 277 // scissoring or background transparency need to be handled. |
| 278 // The Android framework will composite us afterwards. |
| 279 compositor_->SetHasTransparentBackground(false); |
| 280 view_clip_layer_->setMasksToBounds(false); |
| 281 transform_layer_->setTransform(gfx::Transform()); |
| 282 scissor_clip_layer_->setMasksToBounds(false); |
| 283 scissor_clip_layer_->setPosition(gfx::PointF()); |
| 284 scissor_clip_layer_->setBounds(gfx::Size()); |
| 285 scissor_clip_layer_->setSublayerTransform(gfx::Transform()); |
| 286 |
| 287 } else { |
| 288 compositor_->SetHasTransparentBackground(true); |
| 289 |
| 290 gfx::Rect clip_rect(draw_info->clip_left, draw_info->clip_top, |
| 291 draw_info->clip_right - draw_info->clip_left, |
| 292 draw_info->clip_bottom - draw_info->clip_top); |
| 293 |
| 294 scissor_clip_layer_->setPosition(clip_rect.origin()); |
| 295 scissor_clip_layer_->setBounds(clip_rect.size()); |
| 296 scissor_clip_layer_->setMasksToBounds(true); |
| 297 |
| 298 // The compositor clipping architecture enforces us to have the clip layer |
| 299 // as an ancestor of the area we want to clip, but this makes the transform |
| 300 // become relative to the clip area rather than the full surface. The clip |
| 301 // position offset needs to be undone before applying the transform. |
| 302 gfx::Transform undo_clip_position; |
| 303 undo_clip_position.Translate(-clip_rect.x(), -clip_rect.y()); |
| 304 scissor_clip_layer_->setSublayerTransform(undo_clip_position); |
| 305 |
| 306 gfx::Transform transform; |
| 307 transform.matrix().setColMajorf(draw_info->transform); |
| 308 |
| 309 // The scrolling values of the Android Framework affect the transformation |
| 310 // matrix. This needs to be undone to let the compositor handle scrolling. |
| 311 // TODO(leandrogracia): when scrolling becomes synchronous we should undo |
| 312 // or override the translation in the compositor, not the one coming from |
| 313 // the Android View System, as it could be out of bounds for overscrolling. |
| 314 transform.Translate(hw_rendering_scroll_.x(), hw_rendering_scroll_.y()); |
| 315 transform_layer_->setTransform(transform); |
| 316 |
| 317 view_clip_layer_->setMasksToBounds(true); |
| 318 } |
| 319 |
| 320 compositor_->Composite(); |
| 321 is_composite_pending_ = false; |
| 322 |
| 323 // TODO(leandrogracia): remove when crbug.com/164140 is closed. |
| 324 // --------------------------------------------------------------------------- |
| 325 char no_gl_restore_prop[PROP_VALUE_MAX]; |
| 326 __system_property_get("webview.chromium_no_gl_restore", no_gl_restore_prop); |
| 327 if (!strcmp(no_gl_restore_prop, "true")) { |
| 328 LOG(WARNING) << "Android GL functor not restoring the previous GL state."; |
| 329 } else { |
| 330 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_external_oes_binding); |
| 331 glBindBuffer(GL_ARRAY_BUFFER, vertex_array_buffer_binding); |
| 332 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_buffer_binding); |
| 333 |
| 334 glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment); |
| 335 glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment); |
| 336 |
| 337 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(vertex_attrib); ++i) { |
| 338 glVertexAttribPointer(i, vertex_attrib[i].size, |
| 339 vertex_attrib[i].type, vertex_attrib[i].normalized, |
| 340 vertex_attrib[i].stride, vertex_attrib[i].pointer); |
| 341 |
| 342 if (vertex_attrib[i].enabled) |
| 343 glEnableVertexAttribArray(i); |
| 344 else |
| 345 glDisableVertexAttribArray(i); |
| 346 } |
| 347 |
| 348 if (depth_test) |
| 349 glEnable(GL_DEPTH_TEST); |
| 350 else |
| 351 glDisable(GL_DEPTH_TEST); |
| 352 |
| 353 if (cull_face) |
| 354 glEnable(GL_CULL_FACE); |
| 355 else |
| 356 glDisable(GL_CULL_FACE); |
| 357 |
| 358 glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]); |
| 359 |
| 360 if (blend_enabled) |
| 361 glEnable(GL_BLEND); |
| 362 else |
| 363 glDisable(GL_BLEND); |
| 364 |
| 365 glBlendFuncSeparate(blend_src_rgb, blend_dest_rgb, |
| 366 blend_src_alpha, blend_dest_alpha); |
| 367 |
| 368 glActiveTexture(active_texture); |
| 369 |
| 370 glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); |
| 371 |
| 372 if (scissor_test) |
| 373 glEnable(GL_SCISSOR_TEST); |
| 374 else |
| 375 glDisable(GL_SCISSOR_TEST); |
| 376 |
| 377 glScissor(scissor_box[0], scissor_box[1], scissor_box[2], |
| 378 scissor_box[3]); |
| 379 |
| 380 glUseProgram(current_program); |
| 381 } |
| 382 // --------------------------------------------------------------------------- |
| 383 } |
| 384 |
| 385 void BrowserViewRendererImpl::SetScrollForHWFrame(int x, int y) { |
| 386 hw_rendering_scroll_ = gfx::Point(x, y); |
| 387 } |
| 388 |
| 389 bool BrowserViewRendererImpl::DrawSW(jobject java_canvas, |
| 390 const gfx::Rect& clip) { |
| 391 TRACE_EVENT0("android_webview", "BrowserViewRendererImpl::DrawSW"); |
| 392 |
| 393 if (clip.IsEmpty()) |
| 394 return true; |
| 395 |
| 396 AwPixelInfo* pixels; |
| 397 JNIEnv* env = AttachCurrentThread(); |
| 398 |
| 399 // Render into an auxiliary bitmap if pixel info is not available. |
| 400 if (!g_sw_draw_functions || |
| 401 (pixels = g_sw_draw_functions->access_pixels(env, java_canvas)) == NULL) { |
| 402 ScopedJavaLocalRef<jobject> jbitmap(java_helper_->CreateBitmap( |
| 403 env, clip.width(), clip.height())); |
| 404 if (!jbitmap.obj()) |
| 405 return false; |
| 406 |
| 407 if (!RasterizeIntoBitmap(env, jbitmap, clip.x(), clip.y(), |
| 408 base::Bind(&BrowserViewRendererImpl::RenderSW, |
| 409 base::Unretained(this)))) { |
| 410 return false; |
| 411 } |
| 412 |
| 413 ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas); |
| 414 java_helper_->DrawBitmapIntoCanvas(env, jbitmap, jcanvas); |
| 415 return true; |
| 416 } |
| 417 |
| 418 // Draw in a SkCanvas built over the pixel information. |
| 419 bool succeeded = false; |
| 420 { |
| 421 SkBitmap bitmap; |
| 422 bitmap.setConfig(static_cast<SkBitmap::Config>(pixels->config), |
| 423 pixels->width, |
| 424 pixels->height, |
| 425 pixels->row_bytes); |
| 426 bitmap.setPixels(pixels->pixels); |
| 427 SkDevice device(bitmap); |
| 428 SkCanvas canvas(&device); |
| 429 SkMatrix matrix; |
| 430 for (int i = 0; i < 9; i++) |
| 431 matrix.set(i, pixels->matrix[i]); |
| 432 canvas.setMatrix(matrix); |
| 433 |
| 434 SkRegion clip; |
| 435 if (pixels->clip_region_size) { |
| 436 size_t bytes_read = clip.readFromMemory(pixels->clip_region); |
| 437 DCHECK_EQ(pixels->clip_region_size, bytes_read); |
| 438 canvas.setClipRegion(clip); |
| 439 } else { |
| 440 clip.setRect(SkIRect::MakeWH(pixels->width, pixels->height)); |
| 441 } |
| 442 |
| 443 succeeded = RenderSW(&canvas); |
| 444 } |
| 445 |
| 446 g_sw_draw_functions->release_pixels(pixels); |
| 447 return succeeded; |
| 448 } |
| 449 |
| 450 ScopedJavaLocalRef<jobject> BrowserViewRendererImpl::CapturePicture() { |
| 451 skia::RefPtr<SkPicture> picture = GetLastCapturedPicture(); |
| 452 if (!picture || !g_sw_draw_functions) |
| 453 return ScopedJavaLocalRef<jobject>(); |
| 454 |
| 455 JNIEnv* env = AttachCurrentThread(); |
| 456 if (g_is_skia_version_compatible) { |
| 457 return ScopedJavaLocalRef<jobject>(env, |
| 458 g_sw_draw_functions->create_picture(env, picture->clone())); |
| 459 } |
| 460 |
| 461 // If Skia versions are not compatible, workaround it by rasterizing the |
| 462 // picture into a bitmap and drawing it into a new Java picture. |
| 463 ScopedJavaLocalRef<jobject> jbitmap(java_helper_->CreateBitmap( |
| 464 env, picture->width(), picture->height())); |
| 465 if (!jbitmap.obj()) |
| 466 return ScopedJavaLocalRef<jobject>(); |
| 467 |
| 468 if (!RasterizeIntoBitmap(env, jbitmap, 0, 0, |
| 469 base::Bind(&BrowserViewRendererImpl::RenderPicture, |
| 470 base::Unretained(this)))) { |
| 471 return ScopedJavaLocalRef<jobject>(); |
| 472 } |
| 473 |
| 474 return java_helper_->RecordBitmapIntoPicture(env, jbitmap); |
| 475 } |
| 476 |
| 477 void BrowserViewRendererImpl::EnableOnNewPicture(OnNewPictureMode mode) { |
| 478 on_new_picture_mode_ = mode; |
| 479 |
| 480 // TODO(leandrogracia): when SW rendering uses the compositor rather than |
| 481 // picture rasterization, send update the renderer side with the correct |
| 482 // listener state. (For now, we always leave render picture listener enabled). |
| 483 // render_view_host_ext_->EnableCapturePictureCallback(enabled); |
| 484 //DCHECK(view_renderer_host_); |
| 485 //view_renderer_host_->EnableCapturePictureCallback( |
| 486 // on_new_picture_mode_ == kOnNewPictureEnabled); |
| 487 } |
| 488 |
| 489 void BrowserViewRendererImpl::OnVisibilityChanged(bool view_visible, |
| 490 bool window_visible) { |
| 491 view_visible_ = window_visible && view_visible; |
| 492 Invalidate(); |
| 493 } |
| 494 |
| 495 void BrowserViewRendererImpl::OnSizeChanged(int width, int height) { |
| 496 view_size_ = gfx::Size(width, height); |
| 497 view_clip_layer_->setBounds(view_size_); |
| 498 } |
| 499 |
| 500 void BrowserViewRendererImpl::OnAttachedToWindow(int width, int height) { |
| 501 view_size_ = gfx::Size(width, height); |
| 502 view_clip_layer_->setBounds(view_size_); |
| 503 } |
| 504 |
| 505 void BrowserViewRendererImpl::OnDetachedFromWindow() { |
| 506 view_visible_ = false; |
| 507 SetCompositorVisibility(false); |
| 508 } |
| 509 |
| 510 void BrowserViewRendererImpl::ScheduleComposite() { |
| 511 TRACE_EVENT0("android_webview", "BrowserViewRendererImpl::ScheduleComposite"); |
| 512 |
| 513 if (is_composite_pending_) |
| 514 return; |
| 515 |
| 516 is_composite_pending_ = true; |
| 517 Invalidate(); |
| 518 } |
| 519 |
| 520 skia::RefPtr<SkPicture> BrowserViewRendererImpl::GetLastCapturedPicture() { |
| 521 // Use the latest available picture if the listener callback is enabled. |
| 522 skia::RefPtr<SkPicture> picture; |
| 523 if (on_new_picture_mode_ == kOnNewPictureEnabled) |
| 524 picture = RendererPictureMap::GetInstance()->GetRendererPicture( |
| 525 web_contents_->GetRoutingID()); |
| 526 |
| 527 // If not available or not in listener mode get it synchronously. |
| 528 if (!picture) { |
| 529 DCHECK(view_renderer_host_); |
| 530 view_renderer_host_->CapturePictureSync(); |
| 531 picture = RendererPictureMap::GetInstance()->GetRendererPicture( |
| 532 web_contents_->GetRoutingID()); |
| 533 } |
| 534 |
| 535 return picture; |
| 536 } |
| 537 |
| 538 void BrowserViewRendererImpl::OnPictureUpdated(int process_id, |
| 539 int render_view_id) { |
| 540 CHECK_EQ(web_contents_->GetRenderProcessHost()->GetID(), process_id); |
| 541 if (render_view_id != web_contents_->GetRoutingID()) |
| 542 return; |
| 543 |
| 544 // TODO(leandrogracia): this can be made unconditional once software rendering |
| 545 // uses Ubercompositor. Until then this path is required for SW invalidations. |
| 546 if (on_new_picture_mode_ == kOnNewPictureEnabled) |
| 547 client_->OnNewPicture(CapturePicture()); |
| 548 |
| 549 // TODO(leandrogracia): delete when sw rendering uses Ubercompositor. |
| 550 // Invalidation should be provided by the compositor only. |
| 551 Invalidate(); |
| 552 } |
| 553 |
| 554 void BrowserViewRendererImpl::SetCompositorVisibility(bool visible) { |
| 555 if (compositor_visible_ != visible) { |
| 556 compositor_visible_ = visible; |
| 557 compositor_->SetVisible(compositor_visible_); |
| 558 } |
| 559 } |
| 560 |
| 561 void BrowserViewRendererImpl::ResetCompositor() { |
| 562 compositor_.reset(content::Compositor::Create(this)); |
| 563 compositor_->SetRootLayer(scissor_clip_layer_); |
| 564 } |
| 565 |
| 566 void BrowserViewRendererImpl::Invalidate() { |
| 567 if (view_visible_) |
| 568 client_->Invalidate(); |
| 569 |
| 570 // When not in invalidation-only mode onNewPicture will be triggered |
| 571 // from the OnPictureUpdated callback. |
| 572 if (on_new_picture_mode_ == kOnNewPictureInvalidationOnly) |
| 573 client_->OnNewPicture(ScopedJavaLocalRef<jobject>()); |
| 574 } |
| 575 |
| 576 bool BrowserViewRendererImpl::RenderSW(SkCanvas* canvas) { |
| 577 // TODO(leandrogracia): once Ubercompositor is ready and we support software |
| 578 // rendering mode, we should avoid this as much as we can, ideally always. |
| 579 // This includes finding a proper replacement for onDraw calls in hardware |
| 580 // mode with software canvases. http://crbug.com/170086. |
| 581 return RenderPicture(canvas); |
| 582 } |
| 583 |
| 584 bool BrowserViewRendererImpl::RenderPicture(SkCanvas* canvas) { |
| 585 skia::RefPtr<SkPicture> picture = GetLastCapturedPicture(); |
| 586 if (!picture) |
| 587 return false; |
| 588 |
| 589 // Correct device scale. |
| 590 canvas->scale(dpi_scale_, dpi_scale_); |
| 591 |
| 592 picture->draw(canvas); |
| 593 return true; |
| 594 } |
| 595 |
| 596 } // namespace android_webview |
OLD | NEW |