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 |