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