Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "android_webview/browser/test/fake_view_root_impl.h" | |
| 6 | |
| 7 #include "android_webview/browser/browser_view_renderer.h" | |
| 8 #include "android_webview/public/browser/draw_gl.h" | |
| 9 #include "base/message_loop/message_loop_proxy.h" | |
| 10 #include "base/synchronization/waitable_event.h" | |
| 11 #include "base/threading/thread.h" | |
| 12 #include "ui/gl/gl_bindings.h" | |
| 13 | |
| 14 namespace android_webview { | |
| 15 | |
| 16 class FakeViewRootImpl::ScopedMakeCurrent { | |
| 17 public: | |
| 18 ScopedMakeCurrent(FakeViewRootImpl* view_root) : view_root_(view_root) { | |
| 19 DCHECK(!view_root_->context_current_); | |
| 20 view_root_->context_current_ = true; | |
| 21 bool result = view_root_->context_->MakeCurrent(view_root_->surface_.get()); | |
| 22 DCHECK(result); | |
| 23 }; | |
| 24 | |
| 25 ~ScopedMakeCurrent() { | |
| 26 DCHECK(view_root_->context_current_); | |
| 27 view_root_->context_current_ = false; | |
| 28 | |
| 29 // Release the underlying EGLContext. This is required because the real | |
| 30 // GLContextEGL may no longer be current here and to satisfy DCHECK in | |
| 31 // GLContextEGL::IsCurrent. | |
| 32 eglMakeCurrent(view_root_->surface_->GetDisplay(), EGL_NO_SURFACE, | |
| 33 EGL_NO_SURFACE, EGL_NO_CONTEXT); | |
| 34 view_root_->context_->ReleaseCurrent(view_root_->surface_.get()); | |
| 35 } | |
| 36 | |
| 37 private: | |
| 38 FakeViewRootImpl* view_root_; | |
| 39 }; | |
| 40 | |
| 41 FakeViewRootImpl::FakeViewRootImpl(BrowserViewRenderer* view, | |
| 42 ViewRootHooks* hooks, | |
| 43 gfx::Rect location) | |
| 44 : view_(view), | |
| 45 hooks_(hooks), | |
| 46 surface_size_(100, 100), | |
| 47 location_(location), | |
| 48 on_draw_hardware_pending_(false), | |
| 49 functor_(nullptr), | |
| 50 context_current_(false), | |
| 51 weak_ptr_factory_(this) { | |
| 52 DCHECK(view_); | |
| 53 view_->OnAttachedToWindow(location_.width(), location_.height()); | |
| 54 } | |
| 55 | |
| 56 FakeViewRootImpl::~FakeViewRootImpl() { | |
| 57 } | |
| 58 | |
| 59 void FakeViewRootImpl::Detach() { | |
| 60 view_->OnDetachedFromWindow(); | |
| 61 | |
| 62 if (render_thread_loop_) { | |
| 63 base::WaitableEvent completion(true, false); | |
| 64 render_thread_loop_->PostTask( | |
| 65 FROM_HERE, base::Bind(&FakeViewRootImpl::DestroyOnRT, | |
| 66 base::Unretained(this), &completion)); | |
| 67 completion.Wait(); | |
| 68 } | |
| 69 | |
| 70 render_thread_.reset(); | |
| 71 functor_ = nullptr; | |
| 72 } | |
| 73 | |
| 74 void FakeViewRootImpl::RequestDrawGL(bool wait_for_completion) { | |
| 75 base::WaitableEvent completion(true, false); | |
| 76 render_thread_loop_->PostTask( | |
| 77 FROM_HERE, | |
| 78 base::Bind(&FakeViewRootImpl::ProcessFunctorOnRT, base::Unretained(this), | |
| 79 wait_for_completion ? &completion : nullptr)); | |
| 80 if (wait_for_completion) | |
| 81 completion.Wait(); | |
| 82 } | |
| 83 | |
| 84 void FakeViewRootImpl::ProcessFunctorOnRT(base::WaitableEvent* sync) { | |
| 85 AwDrawGLInfo process_info; | |
| 86 process_info.version = kAwDrawGLInfoVersion; | |
| 87 process_info.mode = AwDrawGLInfo::kModeProcess; | |
| 88 | |
| 89 hooks_->WillProcessOnRT(functor_); | |
| 90 { | |
| 91 ScopedMakeCurrent make_current(this); | |
| 92 functor_->DrawGL(&process_info); | |
| 93 } | |
| 94 hooks_->DidProcessOnRT(functor_); | |
| 95 | |
| 96 if (sync) | |
| 97 sync->Signal(); | |
| 98 } | |
| 99 | |
| 100 void FakeViewRootImpl::PostInvalidate() { | |
| 101 if (on_draw_hardware_pending_) | |
| 102 return; | |
| 103 on_draw_hardware_pending_ = true; | |
|
hush (inactive)
2014/12/10 20:07:58
could there be a race condition with line 111?
Pos
boliu
2014/12/10 21:30:32
PostInvalidate and OnDrawHardware are both called
| |
| 104 base::MessageLoopProxy::current()->PostTask( | |
| 105 FROM_HERE, base::Bind(&FakeViewRootImpl::OnDrawHardware, | |
| 106 weak_ptr_factory_.GetWeakPtr())); | |
| 107 } | |
| 108 | |
| 109 void FakeViewRootImpl::OnDrawHardware() { | |
| 110 DCHECK(on_draw_hardware_pending_); | |
| 111 on_draw_hardware_pending_ = false; | |
| 112 | |
| 113 bool success = view_->OnDrawHardware(); | |
| 114 if (success) { | |
| 115 CheckRenderThread(); | |
| 116 | |
| 117 base::WaitableEvent completion(true, false); | |
| 118 render_thread_loop_->PostTask( | |
| 119 FROM_HERE, base::Bind(&FakeViewRootImpl::DrawFunctorOnRT, | |
| 120 base::Unretained(this), &completion)); | |
| 121 completion.Wait(); | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 void FakeViewRootImpl::DrawFunctorOnRT(base::WaitableEvent* sync) { | |
| 126 // Ok to access UI functions until sync is signalled. | |
| 127 gfx::Rect location = location_; | |
| 128 { | |
|
hush (inactive)
2014/12/10 20:07:58
why is this in its own block?
boliu
2014/12/10 21:30:32
So AwDrawGLInfo can't be reused for the kModeDraw
| |
| 129 AwDrawGLInfo process_info; | |
| 130 process_info.version = kAwDrawGLInfoVersion; | |
| 131 process_info.mode = AwDrawGLInfo::kModeSync; | |
| 132 | |
| 133 hooks_->WillSyncOnRT(functor_); | |
| 134 functor_->DrawGL(&process_info); | |
| 135 hooks_->DidSyncOnRT(functor_); | |
| 136 } | |
| 137 sync->Signal(); | |
| 138 | |
| 139 AwDrawGLInfo draw_info; | |
| 140 draw_info.version = kAwDrawGLInfoVersion; | |
| 141 draw_info.mode = AwDrawGLInfo::kModeDraw; | |
| 142 draw_info.clip_left = location.x(); | |
|
hush (inactive)
2014/12/10 20:07:58
just use location_ in this function?
boliu
2014/12/10 21:30:32
I imagined location_ to be UI only.
| |
| 143 draw_info.clip_top = location.y(); | |
| 144 draw_info.clip_right = location.x() + location.width(); | |
| 145 draw_info.clip_bottom = location.y() + location.height(); | |
| 146 draw_info.width = surface_size_.width(); | |
| 147 draw_info.height = surface_size_.height(); | |
| 148 draw_info.is_layer = false; | |
| 149 | |
| 150 draw_info.transform[0] = 1.0; | |
| 151 draw_info.transform[1] = 0.0; | |
| 152 draw_info.transform[2] = 0.0; | |
| 153 draw_info.transform[3] = 0.0; | |
| 154 | |
| 155 draw_info.transform[4] = 0.0; | |
| 156 draw_info.transform[5] = 1.0; | |
| 157 draw_info.transform[6] = 0.0; | |
| 158 draw_info.transform[7] = 0.0; | |
| 159 | |
| 160 draw_info.transform[8] = 0.0; | |
| 161 draw_info.transform[9] = 0.0; | |
| 162 draw_info.transform[10] = 1.0; | |
| 163 draw_info.transform[11] = 0.0; | |
| 164 | |
| 165 draw_info.transform[12] = 0.0; | |
| 166 draw_info.transform[13] = 0.0; | |
| 167 draw_info.transform[14] = 0.0; | |
| 168 draw_info.transform[15] = 1.0; | |
| 169 | |
| 170 hooks_->WillDrawOnRT(functor_); | |
| 171 { | |
| 172 ScopedMakeCurrent make_current(this); | |
| 173 functor_->DrawGL(&draw_info); | |
| 174 } | |
| 175 hooks_->DidDrawOnRT(functor_); | |
| 176 } | |
| 177 | |
| 178 void FakeViewRootImpl::CheckRenderThread() { | |
|
hush (inactive)
2014/12/10 20:07:57
this function is basically "InitializeRenderThread
boliu
2014/12/10 21:30:32
sgtm!
| |
| 179 if (functor_) { | |
| 180 DCHECK(render_thread_.get()); | |
| 181 DCHECK(render_thread_loop_.get()); | |
| 182 return; | |
| 183 } | |
| 184 functor_ = view_->GetAwDrawGLViewContext(); | |
| 185 render_thread_.reset(new base::Thread("TestRenderThread")); | |
| 186 render_thread_->Start(); | |
| 187 render_thread_loop_ = render_thread_->task_runner(); | |
| 188 | |
| 189 base::WaitableEvent completion(true, false); | |
| 190 render_thread_loop_->PostTask( | |
| 191 FROM_HERE, base::Bind(&FakeViewRootImpl::InitializeOnRT, | |
| 192 base::Unretained(this), &completion)); | |
| 193 completion.Wait(); | |
| 194 } | |
| 195 | |
| 196 void FakeViewRootImpl::InitializeOnRT(base::WaitableEvent* sync) { | |
| 197 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(surface_size_); | |
| 198 DCHECK(surface_.get()); | |
| 199 DCHECK(surface_->GetHandle()); | |
| 200 context_ = gfx::GLContext::CreateGLContext(nullptr, surface_.get(), | |
| 201 gfx::PreferDiscreteGpu); | |
| 202 DCHECK(context_.get()); | |
| 203 sync->Signal(); | |
| 204 } | |
| 205 | |
| 206 void FakeViewRootImpl::DestroyOnRT(base::WaitableEvent* sync) { | |
| 207 if (context_) { | |
| 208 DCHECK(!context_->IsCurrent(surface_.get())); | |
| 209 context_ = nullptr; | |
| 210 surface_ = nullptr; | |
| 211 } | |
| 212 sync->Signal(); | |
| 213 } | |
| 214 | |
| 215 } // namespace android_webview | |
| OLD | NEW |