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