Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 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/browser/in_process_renderer/in_process_view_renderer.h " | 5 #include "android_webview/browser/in_process_renderer/in_process_view_renderer.h " |
| 6 | 6 |
| 7 #include "android_webview/public/browser/draw_gl.h" | |
| 7 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "content/public/browser/android/content_view_core.h" | |
| 10 #include "content/public/browser/render_view_host.h" | |
| 11 #include "content/public/browser/web_contents.h" | |
| 8 #include "content/public/renderer/android/synchronous_compositor.h" | 12 #include "content/public/renderer/android/synchronous_compositor.h" |
| 13 #include "ui/gl/gl_bindings.h" | |
| 9 | 14 |
| 10 namespace android_webview { | 15 namespace android_webview { |
| 11 | 16 |
| 17 namespace { | |
| 18 const void* kUserDataKey = &kUserDataKey; | |
| 19 | |
| 20 class UserData : public content::WebContents::Data { | |
| 21 public: | |
| 22 UserData(InProcessViewRenderer* ptr) : instance_(ptr) {} | |
| 23 virtual ~UserData() { | |
| 24 instance_->WebContentsGone(); | |
| 25 } | |
| 26 | |
| 27 static InProcessViewRenderer* GetInstance(content::WebContents* contents) { | |
| 28 if (!contents) | |
| 29 return NULL; | |
| 30 UserData* data = reinterpret_cast<UserData*>( | |
| 31 contents->GetUserData(kUserDataKey)); | |
| 32 return data ? data->instance_ : NULL; | |
| 33 } | |
| 34 | |
| 35 private: | |
| 36 InProcessViewRenderer* instance_; | |
| 37 }; | |
| 38 | |
| 39 } // namespace | |
| 40 | |
| 12 InProcessViewRenderer::InProcessViewRenderer( | 41 InProcessViewRenderer::InProcessViewRenderer( |
| 13 BrowserViewRenderer::Client* client, | 42 BrowserViewRenderer::Client* client, |
| 14 JavaHelper* java_helper) | 43 JavaHelper* java_helper) |
| 15 : BrowserViewRendererImpl(client, java_helper), | 44 : web_contents_(NULL), |
| 16 compositor_(NULL) { | 45 compositor_(NULL), |
| 46 client_(client), | |
| 47 view_visible_(false), | |
| 48 about_to_hardware_draw_(false), | |
| 49 continuous_invalidate_(false), | |
| 50 last_frame_context_(NULL) { | |
| 17 } | 51 } |
| 18 | 52 |
| 19 InProcessViewRenderer::~InProcessViewRenderer() { | 53 InProcessViewRenderer::~InProcessViewRenderer() { |
| 20 if (compositor_) | 54 if (compositor_) |
| 21 compositor_->SetClient(NULL); | 55 compositor_->SetClient(NULL); |
| 56 SetContents(NULL); | |
| 57 } | |
| 58 | |
| 59 // static | |
| 60 InProcessViewRenderer* InProcessViewRenderer::FromWebContents( | |
| 61 content::WebContents* contents) { | |
| 62 return UserData::GetInstance(contents); | |
| 63 } | |
| 64 | |
| 65 // static | |
| 66 BrowserViewRenderer* BrowserViewRenderer::FromId(int render_process_id, | |
| 67 int render_view_id) { | |
| 68 const content::RenderViewHost* rvh = | |
| 69 content::RenderViewHost::FromID(render_process_id, render_view_id); | |
| 70 if (!rvh) return NULL; | |
| 71 return InProcessViewRenderer::FromWebContents( | |
| 72 content::WebContents::FromRenderViewHost(rvh)); | |
| 73 } | |
| 74 | |
| 75 void InProcessViewRenderer::SetContents( | |
| 76 content::ContentViewCore* content_view_core) { | |
| 77 // First remove association from the prior ContentViewCore / WebContents. | |
| 78 if (web_contents_) { | |
| 79 web_contents_->SetUserData(kUserDataKey, NULL); | |
| 80 DCHECK(!web_contents_); // WebContentsGone should have been called. | |
| 81 } | |
| 82 | |
| 83 if (!content_view_core) | |
| 84 return; | |
| 85 | |
| 86 web_contents_ = content_view_core->GetWebContents(); | |
| 87 web_contents_->SetUserData(kUserDataKey, new UserData(this)); | |
| 88 } | |
| 89 | |
| 90 void InProcessViewRenderer::WebContentsGone() { | |
| 91 web_contents_ = NULL; | |
| 22 } | 92 } |
| 23 | 93 |
| 24 void InProcessViewRenderer::BindSynchronousCompositor( | 94 void InProcessViewRenderer::BindSynchronousCompositor( |
| 25 content::SynchronousCompositor* compositor) { | 95 content::SynchronousCompositor* compositor) { |
| 26 DCHECK(compositor && compositor_ != compositor); | 96 DCHECK(compositor && compositor_ != compositor); |
| 27 if (compositor_) | 97 if (compositor_) |
| 28 compositor_->SetClient(NULL); | 98 compositor_->SetClient(NULL); |
| 29 compositor_ = compositor; | 99 compositor_ = compositor; |
| 30 compositor_->SetClient(this); | 100 compositor_->SetClient(this); |
|
joth
2013/05/03 01:26:26
todo: check if also attached to window, and if so
| |
| 31 } | 101 } |
| 32 | 102 |
| 33 bool InProcessViewRenderer::RenderPicture(SkCanvas* canvas) { | 103 bool InProcessViewRenderer::RenderPicture(SkCanvas* canvas) { |
| 34 return compositor_ && compositor_->DemandDrawSw(canvas); | 104 return compositor_ && compositor_->DemandDrawSw(canvas); |
| 35 } | 105 } |
| 36 | 106 |
| 107 void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) { | |
| 108 DCHECK(view_visible_); // TODO(boliu): This can't be false, right..? | |
| 109 DCHECK_EQ(draw_info->mode, AwDrawGLInfo::kModeDraw); | |
| 110 | |
| 111 // We need to watch if the current Android context has changed and enforce | |
| 112 // a clean-up in the compositor. | |
| 113 EGLContext current_context = eglGetCurrentContext(); | |
| 114 if (!current_context) { | |
| 115 LOG(WARNING) << "No current context attached. Skipping composite."; | |
| 116 return; | |
| 117 } | |
| 118 | |
| 119 if (last_frame_context_ != current_context) { | |
| 120 last_frame_context_ = current_context; | |
| 121 // TODO(boliu): Handle context lost | |
| 122 } | |
| 123 | |
| 124 if (!compositor_) | |
| 125 return; // TODO(boliu): Draw background or checkerboard or something? | |
|
joth
2013/05/03 01:26:26
this shouldn't be possible, we should only request
boliu
2013/05/03 05:25:50
Do we ever have to worry about the compositor chan
| |
| 126 | |
| 127 // TODO(boliu): Don't ignore other transforms and whatnot. | |
|
joth
2013/05/03 01:26:26
:)
| |
| 128 about_to_hardware_draw_ = true; | |
| 129 compositor_->DemandDrawHw(gfx::Rect(draw_info->width, draw_info->height)); | |
| 130 about_to_hardware_draw_ = false; | |
| 131 | |
| 132 // The GL functor must ensure these are set to zero before returning. | |
| 133 // Not setting them leads to graphical artifacts that can affect other apps. | |
| 134 glBindBuffer(GL_ARRAY_BUFFER, 0); | |
| 135 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); | |
| 136 | |
| 137 if (continuous_invalidate_) | |
| 138 Invalidate(); | |
| 139 } | |
| 140 | |
| 141 void InProcessViewRenderer::SetScrollForHWFrame(int x, int y) { | |
| 142 // TODO(boliu): Implement | |
| 143 } | |
| 144 | |
| 145 bool InProcessViewRenderer::DrawSW(jobject java_canvas, | |
| 146 const gfx::Rect& clip) { | |
| 147 return false; | |
| 148 } | |
| 149 | |
| 150 base::android::ScopedJavaLocalRef<jobject> | |
| 151 InProcessViewRenderer::CapturePicture() { | |
| 152 return base::android::ScopedJavaLocalRef<jobject>(); | |
| 153 } | |
| 154 | |
| 155 void InProcessViewRenderer::EnableOnNewPicture(OnNewPictureMode mode) { | |
| 156 } | |
| 157 | |
| 158 void InProcessViewRenderer::OnVisibilityChanged(bool view_visible, | |
| 159 bool window_visible) { | |
| 160 view_visible_ = window_visible && view_visible; | |
| 161 // TODO(boliu): Need invalidate here if visible? | |
| 162 } | |
| 163 | |
| 164 void InProcessViewRenderer::OnSizeChanged(int width, int height) { | |
| 165 } | |
| 166 | |
| 167 void InProcessViewRenderer::OnAttachedToWindow(int width, int height) { | |
|
joth
2013/05/03 01:26:26
likewise TODO , if we have a compositor, and iff t
| |
| 168 } | |
| 169 | |
| 170 void InProcessViewRenderer::OnDetachedFromWindow() { | |
| 171 } | |
| 172 | |
| 173 bool InProcessViewRenderer::IsAttachedToWindow() { | |
| 174 return false; | |
| 175 } | |
| 176 | |
| 177 bool InProcessViewRenderer::IsViewVisible() { | |
| 178 return view_visible_; | |
| 179 } | |
| 180 | |
| 181 gfx::Rect InProcessViewRenderer::GetScreenRect() { | |
| 182 return gfx::Rect(); | |
| 183 } | |
| 184 | |
| 37 void InProcessViewRenderer::DidDestroyCompositor( | 185 void InProcessViewRenderer::DidDestroyCompositor( |
| 38 content::SynchronousCompositor* compositor) { | 186 content::SynchronousCompositor* compositor) { |
| 39 // Allow for transient hand-over when two compositors may reference | 187 // Allow for transient hand-over when two compositors may reference |
| 40 // a single client. | 188 // a single client. |
| 41 if (compositor_ == compositor) | 189 if (compositor_ == compositor) |
| 42 compositor_ = NULL; | 190 compositor_ = NULL; |
| 43 } | 191 } |
| 44 | 192 |
| 193 void InProcessViewRenderer::SetContinuousInvalidate(bool invalidate) { | |
| 194 if (continuous_invalidate_ == invalidate) | |
| 195 return; | |
| 196 | |
| 197 continuous_invalidate_ = invalidate; | |
| 198 if (continuous_invalidate_ && !about_to_hardware_draw_) | |
|
joth
2013/05/03 01:26:26
I don't think 'hardware' is important for this. I'
| |
| 199 Invalidate(); | |
|
joth
2013/05/03 01:26:26
TODO - handle not attached to window scenario?
| |
| 200 } | |
| 201 | |
| 202 void InProcessViewRenderer::Invalidate() { | |
| 203 DCHECK(view_visible_); | |
| 204 client_->Invalidate(); | |
| 205 } | |
| 206 | |
| 45 } // namespace android_webview | 207 } // namespace android_webview |
| OLD | NEW |