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