OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "android_webview/native/aw_contents.h" | 5 #include "android_webview/native/aw_contents.h" |
6 | 6 |
7 #include <android/bitmap.h> | |
8 #include <sys/system_properties.h> | |
9 | |
10 #include "android_webview/browser/aw_browser_context.h" | 7 #include "android_webview/browser/aw_browser_context.h" |
11 #include "android_webview/browser/aw_browser_main_parts.h" | 8 #include "android_webview/browser/aw_browser_main_parts.h" |
| 9 #include "android_webview/browser/browser_view_renderer_impl.h" |
12 #include "android_webview/browser/net_disk_cache_remover.h" | 10 #include "android_webview/browser/net_disk_cache_remover.h" |
13 #include "android_webview/browser/renderer_host/aw_render_view_host_ext.h" | 11 #include "android_webview/browser/renderer_host/aw_render_view_host_ext.h" |
14 #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_dele
gate.h" | 12 #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_dele
gate.h" |
15 #include "android_webview/common/aw_hit_test_data.h" | 13 #include "android_webview/common/aw_hit_test_data.h" |
16 #include "android_webview/common/renderer_picture_map.h" | |
17 #include "android_webview/native/aw_browser_dependency_factory.h" | 14 #include "android_webview/native/aw_browser_dependency_factory.h" |
18 #include "android_webview/native/aw_contents_io_thread_client_impl.h" | 15 #include "android_webview/native/aw_contents_io_thread_client_impl.h" |
19 #include "android_webview/native/aw_web_contents_delegate.h" | 16 #include "android_webview/native/aw_web_contents_delegate.h" |
| 17 #include "android_webview/native/java_browser_view_renderer_helper.h" |
20 #include "android_webview/native/state_serializer.h" | 18 #include "android_webview/native/state_serializer.h" |
21 #include "android_webview/public/browser/draw_sw.h" | 19 #include "android_webview/public/browser/draw_gl.h" |
22 #include "base/android/jni_android.h" | 20 #include "base/android/jni_android.h" |
23 #include "base/android/jni_array.h" | 21 #include "base/android/jni_array.h" |
24 #include "base/android/jni_string.h" | 22 #include "base/android/jni_string.h" |
25 #include "base/bind.h" | 23 #include "base/bind.h" |
26 #include "base/callback.h" | 24 #include "base/callback.h" |
27 #include "base/debug/trace_event.h" | |
28 #include "base/message_loop.h" | 25 #include "base/message_loop.h" |
29 #include "base/pickle.h" | 26 #include "base/pickle.h" |
30 #include "base/string16.h" | 27 #include "base/string16.h" |
31 #include "base/supports_user_data.h" | 28 #include "base/supports_user_data.h" |
32 #include "cc/layer.h" | |
33 #include "components/navigation_interception/intercept_navigation_delegate.h" | 29 #include "components/navigation_interception/intercept_navigation_delegate.h" |
34 #include "content/public/browser/android/content_view_core.h" | 30 #include "content/public/browser/android/content_view_core.h" |
35 #include "content/public/browser/browser_thread.h" | 31 #include "content/public/browser/browser_thread.h" |
36 #include "content/public/browser/cert_store.h" | 32 #include "content/public/browser/cert_store.h" |
37 #include "content/public/browser/navigation_entry.h" | 33 #include "content/public/browser/navigation_entry.h" |
38 #include "content/public/browser/render_process_host.h" | 34 #include "content/public/browser/render_process_host.h" |
39 #include "content/public/browser/render_view_host.h" | 35 #include "content/public/browser/render_view_host.h" |
40 #include "content/public/browser/web_contents.h" | 36 #include "content/public/browser/web_contents.h" |
41 #include "content/public/common/ssl_status.h" | 37 #include "content/public/common/ssl_status.h" |
42 #include "jni/AwContents_jni.h" | 38 #include "jni/AwContents_jni.h" |
43 #include "net/base/x509_certificate.h" | 39 #include "net/base/x509_certificate.h" |
44 #include "third_party/skia/include/core/SkBitmap.h" | |
45 #include "third_party/skia/include/core/SkCanvas.h" | |
46 #include "third_party/skia/include/core/SkDevice.h" | |
47 #include "third_party/skia/include/core/SkGraphics.h" | |
48 #include "third_party/skia/include/core/SkPicture.h" | |
49 #include "ui/gfx/android/java_bitmap.h" | 40 #include "ui/gfx/android/java_bitmap.h" |
50 #include "ui/gfx/transform.h" | |
51 #include "ui/gl/gl_bindings.h" | |
52 | 41 |
53 // TODO(leandrogracia): remove when crbug.com/164140 is closed. | 42 struct AwDrawSWFunctionTable; |
54 // Borrowed from gl2ext.h. Cannot be included due to conflicts with | |
55 // gl_bindings.h and the EGL library methods (eglGetCurrentContext). | |
56 #ifndef GL_TEXTURE_EXTERNAL_OES | |
57 #define GL_TEXTURE_EXTERNAL_OES 0x8D65 | |
58 #endif | |
59 | |
60 #ifndef GL_TEXTURE_BINDING_EXTERNAL_OES | |
61 #define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67 | |
62 #endif | |
63 | 43 |
64 using base::android::AttachCurrentThread; | 44 using base::android::AttachCurrentThread; |
65 using base::android::ConvertJavaStringToUTF16; | 45 using base::android::ConvertJavaStringToUTF16; |
66 using base::android::ConvertJavaStringToUTF8; | 46 using base::android::ConvertJavaStringToUTF8; |
67 using base::android::ConvertUTF16ToJavaString; | 47 using base::android::ConvertUTF16ToJavaString; |
68 using base::android::ConvertUTF8ToJavaString; | 48 using base::android::ConvertUTF8ToJavaString; |
69 using base::android::JavaRef; | 49 using base::android::JavaRef; |
70 using base::android::ScopedJavaGlobalRef; | 50 using base::android::ScopedJavaGlobalRef; |
71 using base::android::ScopedJavaLocalRef; | 51 using base::android::ScopedJavaLocalRef; |
72 using components::InterceptNavigationDelegate; | 52 using components::InterceptNavigationDelegate; |
73 using content::BrowserThread; | 53 using content::BrowserThread; |
74 using content::ContentViewCore; | 54 using content::ContentViewCore; |
75 using content::WebContents; | 55 using content::WebContents; |
76 | 56 |
77 extern "C" { | 57 extern "C" { |
78 static AwDrawGLFunction DrawGLFunction; | 58 static AwDrawGLFunction DrawGLFunction; |
79 static void DrawGLFunction(int view_context, | 59 static void DrawGLFunction(int view_context, |
80 AwDrawGLInfo* draw_info, | 60 AwDrawGLInfo* draw_info, |
81 void* spare) { | 61 void* spare) { |
82 // |view_context| is the value that was returned from the java | 62 // |view_context| is the value that was returned from the java |
83 // AwContents.onPrepareDrawGL; this cast must match the code there. | 63 // AwContents.onPrepareDrawGL; this cast must match the code there. |
84 reinterpret_cast<android_webview::AwContents*>(view_context)->DrawGL( | 64 reinterpret_cast<android_webview::BrowserViewRenderer*>(view_context)->DrawGL( |
85 draw_info); | 65 draw_info); |
86 } | 66 } |
87 | |
88 typedef base::Callback<bool(SkCanvas*)> RenderMethod; | |
89 | |
90 static bool RasterizeIntoBitmap(JNIEnv* env, | |
91 jobject jbitmap, | |
92 int scroll_x, | |
93 int scroll_y, | |
94 const RenderMethod& renderer) { | |
95 DCHECK(jbitmap); | |
96 | |
97 AndroidBitmapInfo bitmap_info; | |
98 if (AndroidBitmap_getInfo(env, jbitmap, &bitmap_info) < 0) { | |
99 LOG(WARNING) << "Error getting java bitmap info."; | |
100 return false; | |
101 } | |
102 | |
103 void* pixels = NULL; | |
104 if (AndroidBitmap_lockPixels(env, jbitmap, &pixels) < 0) { | |
105 LOG(WARNING) << "Error locking java bitmap pixels."; | |
106 return false; | |
107 } | |
108 | |
109 bool succeeded = false; | |
110 { | |
111 SkBitmap bitmap; | |
112 bitmap.setConfig(SkBitmap::kARGB_8888_Config, | |
113 bitmap_info.width, | |
114 bitmap_info.height, | |
115 bitmap_info.stride); | |
116 bitmap.setPixels(pixels); | |
117 | |
118 SkDevice device(bitmap); | |
119 SkCanvas canvas(&device); | |
120 canvas.translate(-scroll_x, -scroll_y); | |
121 succeeded = renderer.Run(&canvas); | |
122 } | |
123 | |
124 if (AndroidBitmap_unlockPixels(env, jbitmap) < 0) { | |
125 LOG(WARNING) << "Error unlocking java bitmap pixels."; | |
126 return false; | |
127 } | |
128 | |
129 return succeeded; | |
130 } | |
131 } | 67 } |
132 | 68 |
133 namespace android_webview { | 69 namespace android_webview { |
134 | 70 |
135 namespace { | 71 namespace { |
136 | 72 |
137 AwDrawSWFunctionTable* g_draw_sw_functions = NULL; | 73 static JavaBrowserViewRendererHelper java_renderer_helper; |
138 bool g_is_skia_version_compatible = false; | |
139 | 74 |
140 const void* kAwContentsUserDataKey = &kAwContentsUserDataKey; | 75 const void* kAwContentsUserDataKey = &kAwContentsUserDataKey; |
141 | 76 |
142 class AwContentsUserData : public base::SupportsUserData::Data { | 77 class AwContentsUserData : public base::SupportsUserData::Data { |
143 public: | 78 public: |
144 AwContentsUserData(AwContents* ptr) : contents_(ptr) {} | 79 AwContentsUserData(AwContents* ptr) : contents_(ptr) {} |
145 | 80 |
146 static AwContents* GetContents(WebContents* web_contents) { | 81 static AwContents* GetContents(WebContents* web_contents) { |
147 if (!web_contents) | 82 if (!web_contents) |
148 return NULL; | 83 return NULL; |
(...skipping 24 matching lines...) Expand all Loading... |
173 if (!web_contents) return NULL; | 108 if (!web_contents) return NULL; |
174 return FromWebContents(web_contents); | 109 return FromWebContents(web_contents); |
175 } | 110 } |
176 | 111 |
177 AwContents::AwContents(JNIEnv* env, | 112 AwContents::AwContents(JNIEnv* env, |
178 jobject obj, | 113 jobject obj, |
179 jobject web_contents_delegate) | 114 jobject web_contents_delegate) |
180 : java_ref_(env, obj), | 115 : java_ref_(env, obj), |
181 web_contents_delegate_( | 116 web_contents_delegate_( |
182 new AwWebContentsDelegate(env, web_contents_delegate)), | 117 new AwWebContentsDelegate(env, web_contents_delegate)), |
183 view_visible_(false), | 118 ALLOW_THIS_IN_INITIALIZER_LIST(browser_view_renderer_( |
184 compositor_visible_(false), | 119 BrowserViewRendererImpl::Create(this, &java_renderer_helper))) { |
185 is_composite_pending_(false), | |
186 dpi_scale_(1.0f), | |
187 on_new_picture_mode_(kOnNewPictureDisabled), | |
188 last_frame_context_(NULL) { | |
189 RendererPictureMap::CreateInstance(); | |
190 android_webview::AwBrowserDependencyFactory* dependency_factory = | 120 android_webview::AwBrowserDependencyFactory* dependency_factory = |
191 android_webview::AwBrowserDependencyFactory::GetInstance(); | 121 android_webview::AwBrowserDependencyFactory::GetInstance(); |
192 | 122 |
193 // TODO(joth): rather than create and set the WebContents here, expose the | 123 // TODO(joth): rather than create and set the WebContents here, expose the |
194 // factory method to java side and have that orchestrate the construction | 124 // factory method to java side and have that orchestrate the construction |
195 // order. | 125 // order. |
196 SetWebContents(dependency_factory->CreateWebContents()); | 126 SetWebContents(dependency_factory->CreateWebContents()); |
197 } | 127 } |
198 | 128 |
199 void AwContents::ResetCompositor() { | |
200 compositor_.reset(content::Compositor::Create(this)); | |
201 if (scissor_clip_layer_.get()) | |
202 AttachLayerTree(); | |
203 } | |
204 | |
205 void AwContents::SetWebContents(content::WebContents* web_contents) { | 129 void AwContents::SetWebContents(content::WebContents* web_contents) { |
206 web_contents_.reset(web_contents); | 130 web_contents_.reset(web_contents); |
207 if (find_helper_.get()) { | 131 if (find_helper_.get()) { |
208 find_helper_->SetListener(NULL); | 132 find_helper_->SetListener(NULL); |
209 } | 133 } |
210 icon_helper_.reset(new IconHelper(web_contents_.get())); | 134 icon_helper_.reset(new IconHelper(web_contents_.get())); |
211 icon_helper_->SetListener(this); | 135 icon_helper_->SetListener(this); |
212 web_contents_->SetUserData(kAwContentsUserDataKey, | 136 web_contents_->SetUserData(kAwContentsUserDataKey, |
213 new AwContentsUserData(this)); | 137 new AwContentsUserData(this)); |
214 | |
215 web_contents_->SetDelegate(web_contents_delegate_.get()); | 138 web_contents_->SetDelegate(web_contents_delegate_.get()); |
216 render_view_host_ext_.reset(new AwRenderViewHostExt(web_contents_.get(), | 139 render_view_host_ext_.reset(new AwRenderViewHostExt(web_contents_.get())); |
217 this)); | |
218 ResetCompositor(); | |
219 } | 140 } |
220 | 141 |
221 void AwContents::SetWebContents(JNIEnv* env, jobject obj, jint new_wc) { | 142 void AwContents::SetWebContents(JNIEnv* env, jobject obj, jint new_wc) { |
222 SetWebContents(reinterpret_cast<content::WebContents*>(new_wc)); | 143 SetWebContents(reinterpret_cast<content::WebContents*>(new_wc)); |
223 } | 144 } |
224 | 145 |
225 AwContents::~AwContents() { | 146 AwContents::~AwContents() { |
226 DCHECK(AwContents::FromWebContents(web_contents_.get()) == this); | 147 DCHECK(AwContents::FromWebContents(web_contents_.get()) == this); |
227 web_contents_->RemoveUserData(kAwContentsUserDataKey); | 148 web_contents_->RemoveUserData(kAwContentsUserDataKey); |
228 if (find_helper_.get()) | 149 if (find_helper_.get()) |
229 find_helper_->SetListener(NULL); | 150 find_helper_->SetListener(NULL); |
230 if (icon_helper_.get()) | 151 if (icon_helper_.get()) |
231 icon_helper_->SetListener(NULL); | 152 icon_helper_->SetListener(NULL); |
232 } | 153 } |
233 | 154 |
234 void AwContents::DrawGL(AwDrawGLInfo* draw_info) { | |
235 | |
236 TRACE_EVENT0("AwContents", "AwContents::DrawGL"); | |
237 | |
238 if (view_size_.IsEmpty() || !scissor_clip_layer_ || | |
239 draw_info->mode == AwDrawGLInfo::kModeProcess) | |
240 return; | |
241 | |
242 DCHECK_EQ(draw_info->mode, AwDrawGLInfo::kModeDraw); | |
243 | |
244 SetCompositorVisibility(view_visible_); | |
245 if (!compositor_visible_) | |
246 return; | |
247 | |
248 // TODO(leandrogracia): remove when crbug.com/164140 is closed. | |
249 // --------------------------------------------------------------------------- | |
250 GLint texture_external_oes_binding; | |
251 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_external_oes_binding); | |
252 | |
253 GLint vertex_array_buffer_binding; | |
254 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &vertex_array_buffer_binding); | |
255 | |
256 GLint index_array_buffer_binding; | |
257 glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &index_array_buffer_binding); | |
258 | |
259 GLint pack_alignment; | |
260 glGetIntegerv(GL_PACK_ALIGNMENT, &pack_alignment); | |
261 | |
262 GLint unpack_alignment; | |
263 glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment); | |
264 | |
265 struct { | |
266 GLint enabled; | |
267 GLint size; | |
268 GLint type; | |
269 GLint normalized; | |
270 GLint stride; | |
271 GLvoid* pointer; | |
272 } vertex_attrib[3]; | |
273 | |
274 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(vertex_attrib); ++i) { | |
275 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, | |
276 &vertex_attrib[i].enabled); | |
277 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, | |
278 &vertex_attrib[i].size); | |
279 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, | |
280 &vertex_attrib[i].type); | |
281 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, | |
282 &vertex_attrib[i].normalized); | |
283 glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, | |
284 &vertex_attrib[i].stride); | |
285 glGetVertexAttribPointerv(i, GL_VERTEX_ATTRIB_ARRAY_POINTER, | |
286 &vertex_attrib[i].pointer); | |
287 } | |
288 | |
289 GLboolean depth_test; | |
290 glGetBooleanv(GL_DEPTH_TEST, &depth_test); | |
291 | |
292 GLboolean cull_face; | |
293 glGetBooleanv(GL_CULL_FACE, &cull_face); | |
294 | |
295 GLboolean color_mask[4]; | |
296 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask); | |
297 | |
298 GLboolean blend_enabled; | |
299 glGetBooleanv(GL_BLEND, &blend_enabled); | |
300 | |
301 GLint blend_src_rgb; | |
302 glGetIntegerv(GL_BLEND_SRC_RGB, &blend_src_rgb); | |
303 | |
304 GLint blend_src_alpha; | |
305 glGetIntegerv(GL_BLEND_SRC_ALPHA, &blend_src_alpha); | |
306 | |
307 GLint blend_dest_rgb; | |
308 glGetIntegerv(GL_BLEND_DST_RGB, &blend_dest_rgb); | |
309 | |
310 GLint blend_dest_alpha; | |
311 glGetIntegerv(GL_BLEND_DST_ALPHA, &blend_dest_alpha); | |
312 | |
313 GLint active_texture; | |
314 glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); | |
315 | |
316 GLint viewport[4]; | |
317 glGetIntegerv(GL_VIEWPORT, viewport); | |
318 | |
319 GLboolean scissor_test; | |
320 glGetBooleanv(GL_SCISSOR_TEST, &scissor_test); | |
321 | |
322 GLint scissor_box[4]; | |
323 glGetIntegerv(GL_SCISSOR_BOX, scissor_box); | |
324 | |
325 GLint current_program; | |
326 glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program); | |
327 // --------------------------------------------------------------------------- | |
328 | |
329 // We need to watch if the current Android context has changed and enforce | |
330 // a clean-up in the compositor. | |
331 EGLContext current_context = eglGetCurrentContext(); | |
332 if (!current_context) { | |
333 LOG(WARNING) << "No current context attached. Skipping composite."; | |
334 return; | |
335 } | |
336 | |
337 if (last_frame_context_ != current_context) { | |
338 if (last_frame_context_) | |
339 ResetCompositor(); | |
340 last_frame_context_ = current_context; | |
341 } | |
342 | |
343 compositor_->SetWindowBounds(gfx::Size(draw_info->width, draw_info->height)); | |
344 | |
345 if (draw_info->is_layer) { | |
346 // When rendering into a separate layer no view clipping, transform, | |
347 // scissoring or background transparency need to be handled. | |
348 // The Android framework will composite us afterwards. | |
349 compositor_->SetHasTransparentBackground(false); | |
350 view_clip_layer_->setMasksToBounds(false); | |
351 transform_layer_->setTransform(gfx::Transform()); | |
352 scissor_clip_layer_->setMasksToBounds(false); | |
353 scissor_clip_layer_->setPosition(gfx::PointF()); | |
354 scissor_clip_layer_->setBounds(gfx::Size()); | |
355 scissor_clip_layer_->setSublayerTransform(gfx::Transform()); | |
356 | |
357 } else { | |
358 compositor_->SetHasTransparentBackground(true); | |
359 | |
360 gfx::Rect clip_rect(draw_info->clip_left, draw_info->clip_top, | |
361 draw_info->clip_right - draw_info->clip_left, | |
362 draw_info->clip_bottom - draw_info->clip_top); | |
363 | |
364 scissor_clip_layer_->setPosition(clip_rect.origin()); | |
365 scissor_clip_layer_->setBounds(clip_rect.size()); | |
366 scissor_clip_layer_->setMasksToBounds(true); | |
367 | |
368 // The compositor clipping architecture enforces us to have the clip layer | |
369 // as an ancestor of the area we want to clip, but this makes the transform | |
370 // become relative to the clip area rather than the full surface. The clip | |
371 // position offset needs to be undone before applying the transform. | |
372 gfx::Transform undo_clip_position; | |
373 undo_clip_position.Translate(-clip_rect.x(), -clip_rect.y()); | |
374 scissor_clip_layer_->setSublayerTransform(undo_clip_position); | |
375 | |
376 gfx::Transform transform; | |
377 transform.matrix().setColMajorf(draw_info->transform); | |
378 | |
379 // The scrolling values of the Android Framework affect the transformation | |
380 // matrix. This needs to be undone to let the compositor handle scrolling. | |
381 transform.Translate(hw_rendering_scroll_.x(), hw_rendering_scroll_.y()); | |
382 transform_layer_->setTransform(transform); | |
383 | |
384 view_clip_layer_->setMasksToBounds(true); | |
385 } | |
386 | |
387 compositor_->Composite(); | |
388 is_composite_pending_ = false; | |
389 | |
390 // TODO(leandrogracia): remove when crbug.com/164140 is closed. | |
391 // --------------------------------------------------------------------------- | |
392 char no_gl_restore_prop[PROP_VALUE_MAX]; | |
393 __system_property_get("webview.chromium_no_gl_restore", no_gl_restore_prop); | |
394 if (!strcmp(no_gl_restore_prop, "true")) { | |
395 LOG(WARNING) << "Android GL functor not restoring the previous GL state."; | |
396 } else { | |
397 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_external_oes_binding); | |
398 glBindBuffer(GL_ARRAY_BUFFER, vertex_array_buffer_binding); | |
399 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_buffer_binding); | |
400 | |
401 glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment); | |
402 glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment); | |
403 | |
404 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(vertex_attrib); ++i) { | |
405 glVertexAttribPointer(i, vertex_attrib[i].size, | |
406 vertex_attrib[i].type, vertex_attrib[i].normalized, | |
407 vertex_attrib[i].stride, vertex_attrib[i].pointer); | |
408 | |
409 if (vertex_attrib[i].enabled) | |
410 glEnableVertexAttribArray(i); | |
411 else | |
412 glDisableVertexAttribArray(i); | |
413 } | |
414 | |
415 if (depth_test) | |
416 glEnable(GL_DEPTH_TEST); | |
417 else | |
418 glDisable(GL_DEPTH_TEST); | |
419 | |
420 if (cull_face) | |
421 glEnable(GL_CULL_FACE); | |
422 else | |
423 glDisable(GL_CULL_FACE); | |
424 | |
425 glColorMask(color_mask[0], color_mask[1], color_mask[2], | |
426 color_mask[3]); | |
427 | |
428 if (blend_enabled) | |
429 glEnable(GL_BLEND); | |
430 else | |
431 glDisable(GL_BLEND); | |
432 | |
433 glBlendFuncSeparate(blend_src_rgb, blend_dest_rgb, | |
434 blend_src_alpha, blend_dest_alpha); | |
435 | |
436 glActiveTexture(active_texture); | |
437 | |
438 glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); | |
439 | |
440 if (scissor_test) | |
441 glEnable(GL_SCISSOR_TEST); | |
442 else | |
443 glDisable(GL_SCISSOR_TEST); | |
444 | |
445 glScissor(scissor_box[0], scissor_box[1], scissor_box[2], | |
446 scissor_box[3]); | |
447 | |
448 glUseProgram(current_program); | |
449 } | |
450 // --------------------------------------------------------------------------- | |
451 } | |
452 | |
453 bool AwContents::DrawSW(JNIEnv* env, | |
454 jobject obj, | |
455 jobject java_canvas, | |
456 jint clip_x, | |
457 jint clip_y, | |
458 jint clip_w, | |
459 jint clip_h) { | |
460 TRACE_EVENT0("AwContents", "AwContents::DrawSW"); | |
461 | |
462 if (clip_w <= 0 || clip_h <= 0) | |
463 return true; | |
464 | |
465 AwPixelInfo* pixels; | |
466 | |
467 // Render into an auxiliary bitmap if pixel info is not available. | |
468 if (!g_draw_sw_functions || | |
469 (pixels = g_draw_sw_functions->access_pixels(env, java_canvas)) == NULL) { | |
470 ScopedJavaLocalRef<jobject> jbitmap(Java_AwContents_createBitmap( | |
471 env, clip_w, clip_h)); | |
472 if (!jbitmap.obj()) | |
473 return false; | |
474 | |
475 if (!RasterizeIntoBitmap(env, jbitmap.obj(), clip_x, clip_y, | |
476 base::Bind(&AwContents::RenderSW, base::Unretained(this)))) | |
477 return false; | |
478 | |
479 Java_AwContents_drawBitmapIntoCanvas(env, jbitmap.obj(), java_canvas); | |
480 return true; | |
481 } | |
482 | |
483 // Draw in a SkCanvas built over the pixel information. | |
484 bool succeeded = false; | |
485 { | |
486 SkBitmap bitmap; | |
487 bitmap.setConfig(static_cast<SkBitmap::Config>(pixels->config), | |
488 pixels->width, | |
489 pixels->height, | |
490 pixels->row_bytes); | |
491 bitmap.setPixels(pixels->pixels); | |
492 SkDevice device(bitmap); | |
493 SkCanvas canvas(&device); | |
494 SkMatrix matrix; | |
495 for (int i = 0; i < 9; i++) | |
496 matrix.set(i, pixels->matrix[i]); | |
497 canvas.setMatrix(matrix); | |
498 | |
499 SkRegion clip; | |
500 if (pixels->clip_region_size) { | |
501 size_t bytes_read = clip.readFromMemory(pixels->clip_region); | |
502 DCHECK_EQ(pixels->clip_region_size, bytes_read); | |
503 canvas.setClipRegion(clip); | |
504 } else { | |
505 clip.setRect(SkIRect::MakeWH(pixels->width, pixels->height)); | |
506 } | |
507 | |
508 succeeded = RenderSW(&canvas); | |
509 } | |
510 | |
511 g_draw_sw_functions->release_pixels(pixels); | |
512 return succeeded; | |
513 } | |
514 | |
515 jint AwContents::GetWebContents(JNIEnv* env, jobject obj) { | 155 jint AwContents::GetWebContents(JNIEnv* env, jobject obj) { |
516 return reinterpret_cast<jint>(web_contents_.get()); | 156 return reinterpret_cast<jint>(web_contents_.get()); |
517 } | 157 } |
518 | 158 |
519 void AwContents::DidInitializeContentViewCore(JNIEnv* env, jobject obj, | 159 void AwContents::DidInitializeContentViewCore(JNIEnv* env, jobject obj, |
520 jint content_view_core) { | 160 jint content_view_core) { |
521 ContentViewCore* core = reinterpret_cast<ContentViewCore*>(content_view_core); | 161 ContentViewCore* core = reinterpret_cast<ContentViewCore*>(content_view_core); |
522 DCHECK(core == ContentViewCore::FromWebContents(web_contents_.get())); | 162 DCHECK(core == ContentViewCore::FromWebContents(web_contents_.get())); |
523 | 163 browser_view_renderer_->SetContents(core); |
524 dpi_scale_ = core->GetDpiScale(); | |
525 | |
526 // Ensures content keeps clipped within the view during transformations. | |
527 view_clip_layer_ = cc::Layer::create(); | |
528 view_clip_layer_->setBounds(view_size_); | |
529 view_clip_layer_->addChild(core->GetLayer()); | |
530 | |
531 // Applies the transformation matrix. | |
532 transform_layer_ = cc::Layer::create(); | |
533 transform_layer_->addChild(view_clip_layer_); | |
534 | |
535 // Ensures content is drawn within the scissor clip rect provided by the | |
536 // Android framework. | |
537 scissor_clip_layer_ = cc::Layer::create(); | |
538 scissor_clip_layer_->addChild(transform_layer_); | |
539 | |
540 AttachLayerTree(); | |
541 } | |
542 | |
543 void AwContents::AttachLayerTree() { | |
544 DCHECK(scissor_clip_layer_.get()); | |
545 compositor_->SetRootLayer(scissor_clip_layer_); | |
546 Invalidate(); | |
547 } | 164 } |
548 | 165 |
549 void AwContents::Destroy(JNIEnv* env, jobject obj) { | 166 void AwContents::Destroy(JNIEnv* env, jobject obj) { |
550 delete this; | 167 delete this; |
551 } | 168 } |
552 | 169 |
553 // static | 170 // static |
554 void SetAwDrawSWFunctionTable(JNIEnv* env, jclass, jint function_table) { | 171 void SetAwDrawSWFunctionTable(JNIEnv* env, jclass, jint function_table) { |
555 g_draw_sw_functions = | 172 BrowserViewRendererImpl::SetAwDrawSWFunctionTable( |
556 reinterpret_cast<AwDrawSWFunctionTable*>(function_table); | 173 reinterpret_cast<AwDrawSWFunctionTable*>(function_table)); |
557 g_is_skia_version_compatible = | |
558 g_draw_sw_functions->is_skia_version_compatible(&SkGraphics::GetVersion); | |
559 LOG_IF(WARNING, !g_is_skia_version_compatible) << | |
560 "Skia native versions are not compatible."; | |
561 } | 174 } |
562 | 175 |
563 // static | 176 // static |
564 jint GetAwDrawGLFunction(JNIEnv* env, jclass) { | 177 jint GetAwDrawGLFunction(JNIEnv* env, jclass) { |
565 return reinterpret_cast<jint>(&DrawGLFunction); | 178 return reinterpret_cast<jint>(&DrawGLFunction); |
566 } | 179 } |
567 | 180 |
| 181 jint AwContents::GetAwDrawGLViewContext(JNIEnv* env, jobject obj) { |
| 182 return reinterpret_cast<jint>(browser_view_renderer_.get()); |
| 183 } |
| 184 |
568 namespace { | 185 namespace { |
569 void DocumentHasImagesCallback(const ScopedJavaGlobalRef<jobject>& message, | 186 void DocumentHasImagesCallback(const ScopedJavaGlobalRef<jobject>& message, |
570 bool has_images) { | 187 bool has_images) { |
571 Java_AwContents_onDocumentHasImagesResponse(AttachCurrentThread(), | 188 Java_AwContents_onDocumentHasImagesResponse(AttachCurrentThread(), |
572 has_images, | 189 has_images, |
573 message.obj()); | 190 message.obj()); |
574 } | 191 } |
575 } // namespace | 192 } // namespace |
576 | 193 |
577 void AwContents::DocumentHasImages(JNIEnv* env, jobject obj, jobject message) { | 194 void AwContents::DocumentHasImages(JNIEnv* env, jobject obj, jobject message) { |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
883 bool precomposed) { | 500 bool precomposed) { |
884 JNIEnv* env = AttachCurrentThread(); | 501 JNIEnv* env = AttachCurrentThread(); |
885 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | 502 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); |
886 if (obj.is_null()) | 503 if (obj.is_null()) |
887 return; | 504 return; |
888 | 505 |
889 Java_AwContents_onReceivedTouchIconUrl( | 506 Java_AwContents_onReceivedTouchIconUrl( |
890 env, obj.obj(), ConvertUTF8ToJavaString(env, url).obj(), precomposed); | 507 env, obj.obj(), ConvertUTF8ToJavaString(env, url).obj(), precomposed); |
891 } | 508 } |
892 | 509 |
893 void AwContents::ScheduleComposite() { | |
894 TRACE_EVENT0("AwContents", "AwContents::ScheduleComposite"); | |
895 | |
896 if (is_composite_pending_) | |
897 return; | |
898 | |
899 is_composite_pending_ = true; | |
900 Invalidate(); | |
901 } | |
902 | |
903 void AwContents::Invalidate() { | 510 void AwContents::Invalidate() { |
904 JNIEnv* env = AttachCurrentThread(); | 511 JNIEnv* env = AttachCurrentThread(); |
905 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | 512 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); |
906 if (obj.is_null()) | 513 if (!obj.is_null()) |
907 return; | |
908 | |
909 if (view_visible_) | |
910 Java_AwContents_invalidate(env, obj.obj()); | 514 Java_AwContents_invalidate(env, obj.obj()); |
911 | |
912 // When not in invalidation-only mode onNewPicture will be triggered | |
913 // from the OnPictureUpdated callback. | |
914 if (on_new_picture_mode_ == kOnNewPictureInvalidationOnly) | |
915 Java_AwContents_onNewPicture(env, obj.obj(), NULL); | |
916 } | 515 } |
917 | 516 |
918 void AwContents::SetCompositorVisibility(bool visible) { | 517 void AwContents::OnNewPicture(const JavaRef<jobject>& picture) { |
919 if (compositor_visible_ != visible) { | 518 JNIEnv* env = AttachCurrentThread(); |
920 compositor_visible_ = visible; | 519 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); |
921 compositor_->SetVisible(compositor_visible_); | 520 if (!obj.is_null()) |
922 } | 521 Java_AwContents_onNewPicture(env, obj.obj(), picture.obj()); |
923 } | |
924 | |
925 void AwContents::OnSwapBuffersCompleted() { | |
926 } | 522 } |
927 | 523 |
928 base::android::ScopedJavaLocalRef<jbyteArray> | 524 base::android::ScopedJavaLocalRef<jbyteArray> |
929 AwContents::GetCertificate(JNIEnv* env, | 525 AwContents::GetCertificate(JNIEnv* env, |
930 jobject obj) { | 526 jobject obj) { |
931 content::NavigationEntry* entry = | 527 content::NavigationEntry* entry = |
932 web_contents_->GetController().GetActiveEntry(); | 528 web_contents_->GetController().GetActiveEntry(); |
933 if (!entry) | 529 if (!entry) |
934 return ScopedJavaLocalRef<jbyteArray>(); | 530 return ScopedJavaLocalRef<jbyteArray>(); |
935 // Get the certificate | 531 // Get the certificate |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
979 obj, | 575 obj, |
980 data.type, | 576 data.type, |
981 extra_data_for_type.obj(), | 577 extra_data_for_type.obj(), |
982 href.obj(), | 578 href.obj(), |
983 anchor_text.obj(), | 579 anchor_text.obj(), |
984 img_src.obj()); | 580 img_src.obj()); |
985 } | 581 } |
986 | 582 |
987 void AwContents::OnSizeChanged(JNIEnv* env, jobject obj, | 583 void AwContents::OnSizeChanged(JNIEnv* env, jobject obj, |
988 int w, int h, int ow, int oh) { | 584 int w, int h, int ow, int oh) { |
989 view_size_ = gfx::Size(w, h); | 585 browser_view_renderer_->OnSizeChanged(w, h); |
990 if (view_clip_layer_.get()) | |
991 view_clip_layer_->setBounds(view_size_); | |
992 } | 586 } |
993 | 587 |
994 void AwContents::SetWindowViewVisibility(JNIEnv* env, jobject obj, | 588 void AwContents::SetWindowViewVisibility(JNIEnv* env, jobject obj, |
995 bool window_visible, | 589 bool window_visible, |
996 bool view_visible) { | 590 bool view_visible) { |
997 view_visible_ = window_visible && view_visible; | 591 browser_view_renderer_->OnVisibilityChanged(window_visible, view_visible); |
998 Invalidate(); | |
999 } | 592 } |
1000 | 593 |
1001 void AwContents::OnAttachedToWindow(JNIEnv* env, jobject obj, int w, int h) { | 594 void AwContents::OnAttachedToWindow(JNIEnv* env, jobject obj, int w, int h) { |
1002 view_size_ = gfx::Size(w, h); | 595 browser_view_renderer_->OnAttachedToWindow(w, h); |
1003 if (view_clip_layer_.get()) | |
1004 view_clip_layer_->setBounds(view_size_); | |
1005 } | 596 } |
1006 | 597 |
1007 void AwContents::OnDetachedFromWindow(JNIEnv* env, jobject obj) { | 598 void AwContents::OnDetachedFromWindow(JNIEnv* env, jobject obj) { |
1008 view_visible_ = false; | 599 browser_view_renderer_->OnDetachedFromWindow(); |
1009 SetCompositorVisibility(false); | |
1010 } | 600 } |
1011 | 601 |
1012 base::android::ScopedJavaLocalRef<jbyteArray> | 602 base::android::ScopedJavaLocalRef<jbyteArray> |
1013 AwContents::GetOpaqueState(JNIEnv* env, jobject obj) { | 603 AwContents::GetOpaqueState(JNIEnv* env, jobject obj) { |
1014 // Required optimization in WebViewClassic to not save any state if | 604 // Required optimization in WebViewClassic to not save any state if |
1015 // there has been no navigations. | 605 // there has been no navigations. |
1016 if (!web_contents_->GetController().GetEntryCount()) | 606 if (!web_contents_->GetController().GetEntryCount()) |
1017 return ScopedJavaLocalRef<jbyteArray>(); | 607 return ScopedJavaLocalRef<jbyteArray>(); |
1018 | 608 |
1019 Pickle pickle; | 609 Pickle pickle; |
(...skipping 12 matching lines...) Expand all Loading... |
1032 std::vector<uint8> state_vector; | 622 std::vector<uint8> state_vector; |
1033 base::android::JavaByteArrayToByteVector(env, state, &state_vector); | 623 base::android::JavaByteArrayToByteVector(env, state, &state_vector); |
1034 | 624 |
1035 Pickle pickle(reinterpret_cast<const char*>(state_vector.begin()), | 625 Pickle pickle(reinterpret_cast<const char*>(state_vector.begin()), |
1036 state_vector.size()); | 626 state_vector.size()); |
1037 PickleIterator iterator(pickle); | 627 PickleIterator iterator(pickle); |
1038 | 628 |
1039 return RestoreFromPickle(&iterator, web_contents_.get()); | 629 return RestoreFromPickle(&iterator, web_contents_.get()); |
1040 } | 630 } |
1041 | 631 |
| 632 bool AwContents::DrawSW(JNIEnv* env, |
| 633 jobject obj, |
| 634 jobject canvas, |
| 635 jint clip_x, |
| 636 jint clip_y, |
| 637 jint clip_w, |
| 638 jint clip_h) { |
| 639 return browser_view_renderer_->DrawSW( |
| 640 canvas, gfx::Rect(clip_x, clip_y, clip_w, clip_h)); |
| 641 } |
| 642 |
1042 void AwContents::SetScrollForHWFrame(JNIEnv* env, jobject obj, | 643 void AwContents::SetScrollForHWFrame(JNIEnv* env, jobject obj, |
1043 int scroll_x, int scroll_y) { | 644 int scroll_x, int scroll_y) { |
1044 hw_rendering_scroll_ = gfx::Point(scroll_x, scroll_y); | 645 browser_view_renderer_->SetScrollForHWFrame(scroll_x, scroll_y); |
1045 } | 646 } |
1046 | 647 |
1047 void AwContents::SetPendingWebContentsForPopup( | 648 void AwContents::SetPendingWebContentsForPopup( |
1048 scoped_ptr<content::WebContents> pending) { | 649 scoped_ptr<content::WebContents> pending) { |
1049 if (pending_contents_.get()) { | 650 if (pending_contents_.get()) { |
1050 // TODO(benm): Support holding multiple pop up window requests. | 651 // TODO(benm): Support holding multiple pop up window requests. |
1051 LOG(WARNING) << "Blocking popup window creation as an outstanding " | 652 LOG(WARNING) << "Blocking popup window creation as an outstanding " |
1052 << "popup window is still pending."; | 653 << "popup window is still pending."; |
1053 MessageLoop::current()->DeleteSoon(FROM_HERE, pending.release()); | 654 MessageLoop::current()->DeleteSoon(FROM_HERE, pending.release()); |
1054 return; | 655 return; |
1055 } | 656 } |
1056 pending_contents_ = pending.Pass(); | 657 pending_contents_ = pending.Pass(); |
1057 } | 658 } |
1058 | 659 |
1059 void AwContents::FocusFirstNode(JNIEnv* env, jobject obj) { | 660 void AwContents::FocusFirstNode(JNIEnv* env, jobject obj) { |
1060 web_contents_->FocusThroughTabTraversal(false); | 661 web_contents_->FocusThroughTabTraversal(false); |
1061 } | 662 } |
1062 | 663 |
1063 jint AwContents::ReleasePopupWebContents(JNIEnv* env, jobject obj) { | 664 jint AwContents::ReleasePopupWebContents(JNIEnv* env, jobject obj) { |
1064 return reinterpret_cast<jint>(pending_contents_.release()); | 665 return reinterpret_cast<jint>(pending_contents_.release()); |
1065 } | 666 } |
1066 | 667 |
1067 ScopedJavaLocalRef<jobject> AwContents::CapturePicture(JNIEnv* env, | 668 ScopedJavaLocalRef<jobject> AwContents::CapturePicture(JNIEnv* env, |
1068 jobject obj) { | 669 jobject obj) { |
1069 skia::RefPtr<SkPicture> picture = GetLastCapturedPicture(); | 670 return browser_view_renderer_->CapturePicture(); |
1070 if (!picture || !g_draw_sw_functions) | |
1071 return ScopedJavaLocalRef<jobject>(); | |
1072 | |
1073 if (g_is_skia_version_compatible) | |
1074 return ScopedJavaLocalRef<jobject>(env, | |
1075 g_draw_sw_functions->create_picture(env, picture->clone())); | |
1076 | |
1077 // If Skia versions are not compatible, workaround it by rasterizing the | |
1078 // picture into a bitmap and drawing it into a new Java picture. | |
1079 ScopedJavaLocalRef<jobject> jbitmap(Java_AwContents_createBitmap( | |
1080 env, picture->width(), picture->height())); | |
1081 if (!jbitmap.obj()) | |
1082 return ScopedJavaLocalRef<jobject>(); | |
1083 | |
1084 if (!RasterizeIntoBitmap(env, jbitmap.obj(), 0, 0, | |
1085 base::Bind(&AwContents::RenderPicture, base::Unretained(this)))) | |
1086 return ScopedJavaLocalRef<jobject>(); | |
1087 | |
1088 return Java_AwContents_recordBitmapIntoPicture(env, jbitmap.obj()); | |
1089 } | |
1090 | |
1091 bool AwContents::RenderSW(SkCanvas* canvas) { | |
1092 // TODO(leandrogracia): once Ubercompositor is ready and we support software | |
1093 // rendering mode, we should avoid this as much as we can, ideally always. | |
1094 // This includes finding a proper replacement for onDraw calls in hardware | |
1095 // mode with software canvases. http://crbug.com/170086. | |
1096 return RenderPicture(canvas); | |
1097 } | |
1098 | |
1099 bool AwContents::RenderPicture(SkCanvas* canvas) { | |
1100 skia::RefPtr<SkPicture> picture = GetLastCapturedPicture(); | |
1101 if (!picture) | |
1102 return false; | |
1103 | |
1104 // Correct device scale. | |
1105 canvas->scale(dpi_scale_, dpi_scale_); | |
1106 | |
1107 picture->draw(canvas); | |
1108 return true; | |
1109 } | 671 } |
1110 | 672 |
1111 void AwContents::EnableOnNewPicture(JNIEnv* env, | 673 void AwContents::EnableOnNewPicture(JNIEnv* env, |
1112 jobject obj, | 674 jobject obj, |
1113 jboolean enabled, | 675 jboolean enabled, |
1114 jboolean invalidation_only) { | 676 jboolean invalidation_only) { |
| 677 BrowserViewRenderer::OnNewPictureMode mode = |
| 678 BrowserViewRenderer::kOnNewPictureDisabled; |
1115 if (enabled) { | 679 if (enabled) { |
1116 on_new_picture_mode_ = invalidation_only ? kOnNewPictureInvalidationOnly : | 680 mode = invalidation_only ? |
1117 kOnNewPictureEnabled; | 681 BrowserViewRenderer::kOnNewPictureInvalidationOnly : |
1118 } else { | 682 BrowserViewRenderer::kOnNewPictureEnabled; |
1119 on_new_picture_mode_ = kOnNewPictureDisabled; | |
1120 } | 683 } |
1121 | 684 |
1122 // If onNewPicture is triggered only on invalidation do not capture | 685 browser_view_renderer_->EnableOnNewPicture(mode); |
1123 // pictures on every new frame. | |
1124 if (on_new_picture_mode_ == kOnNewPictureInvalidationOnly) | |
1125 enabled = false; | |
1126 | |
1127 // TODO(leandrogracia): when SW rendering uses the compositor rather than | |
1128 // picture rasterization, send update the renderer side with the correct | |
1129 // listener state. (For now, we always leave render picture listener enabled). | |
1130 // render_view_host_ext_->EnableCapturePictureCallback(enabled); | |
1131 } | |
1132 | |
1133 void AwContents::OnPictureUpdated(int process_id, int render_view_id) { | |
1134 CHECK_EQ(web_contents_->GetRenderProcessHost()->GetID(), process_id); | |
1135 if (render_view_id != web_contents_->GetRoutingID()) | |
1136 return; | |
1137 | |
1138 // TODO(leandrogracia): this can be made unconditional once software rendering | |
1139 // uses Ubercompositor. Until then this path is required for SW invalidations. | |
1140 if (on_new_picture_mode_ == kOnNewPictureEnabled) { | |
1141 JNIEnv* env = AttachCurrentThread(); | |
1142 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | |
1143 if (!obj.is_null()) { | |
1144 ScopedJavaLocalRef<jobject> picture = CapturePicture(env, obj.obj()); | |
1145 Java_AwContents_onNewPicture(env, obj.obj(), picture.obj()); | |
1146 } | |
1147 } | |
1148 | |
1149 // TODO(leandrogracia): delete when sw rendering uses Ubercompositor. | |
1150 // Invalidation should be provided by the compositor only. | |
1151 Invalidate(); | |
1152 } | |
1153 | |
1154 skia::RefPtr<SkPicture> AwContents::GetLastCapturedPicture() { | |
1155 // Use the latest available picture if the listener callback is enabled. | |
1156 skia::RefPtr<SkPicture> picture; | |
1157 if (on_new_picture_mode_ == kOnNewPictureEnabled) | |
1158 picture = RendererPictureMap::GetInstance()->GetRendererPicture( | |
1159 web_contents_->GetRoutingID()); | |
1160 | |
1161 // If not available or not in listener mode get it synchronously. | |
1162 if (!picture) { | |
1163 render_view_host_ext_->CapturePictureSync(); | |
1164 picture = RendererPictureMap::GetInstance()->GetRendererPicture( | |
1165 web_contents_->GetRoutingID()); | |
1166 } | |
1167 | |
1168 return picture; | |
1169 } | 686 } |
1170 | 687 |
1171 } // namespace android_webview | 688 } // namespace android_webview |
OLD | NEW |