| 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_window.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 FakeWindow::ScopedMakeCurrent { | 
|  | 17  public: | 
|  | 18   ScopedMakeCurrent(FakeWindow* 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   FakeWindow* view_root_; | 
|  | 39 }; | 
|  | 40 | 
|  | 41 FakeWindow::FakeWindow(BrowserViewRenderer* view, | 
|  | 42                        WindowHooks* 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   CheckCurrentlyOnUIThread(); | 
|  | 53   DCHECK(view_); | 
|  | 54   view_->OnAttachedToWindow(location_.width(), location_.height()); | 
|  | 55 } | 
|  | 56 | 
|  | 57 FakeWindow::~FakeWindow() { | 
|  | 58   CheckCurrentlyOnUIThread(); | 
|  | 59 } | 
|  | 60 | 
|  | 61 void FakeWindow::Detach() { | 
|  | 62   CheckCurrentlyOnUIThread(); | 
|  | 63   view_->OnDetachedFromWindow(); | 
|  | 64 | 
|  | 65   if (render_thread_loop_) { | 
|  | 66     base::WaitableEvent completion(true, false); | 
|  | 67     render_thread_loop_->PostTask( | 
|  | 68         FROM_HERE, base::Bind(&FakeWindow::DestroyOnRT, base::Unretained(this), | 
|  | 69                               &completion)); | 
|  | 70     completion.Wait(); | 
|  | 71   } | 
|  | 72 | 
|  | 73   render_thread_.reset(); | 
|  | 74   functor_ = nullptr; | 
|  | 75 } | 
|  | 76 | 
|  | 77 void FakeWindow::RequestDrawGL(bool wait_for_completion) { | 
|  | 78   CheckCurrentlyOnUIThread(); | 
|  | 79   base::WaitableEvent completion(true, false); | 
|  | 80   render_thread_loop_->PostTask( | 
|  | 81       FROM_HERE, | 
|  | 82       base::Bind(&FakeWindow::ProcessFunctorOnRT, base::Unretained(this), | 
|  | 83                  wait_for_completion ? &completion : nullptr)); | 
|  | 84   if (wait_for_completion) | 
|  | 85     completion.Wait(); | 
|  | 86 } | 
|  | 87 | 
|  | 88 void FakeWindow::ProcessFunctorOnRT(base::WaitableEvent* sync) { | 
|  | 89   CheckCurrentlyOnRT(); | 
|  | 90   AwDrawGLInfo process_info; | 
|  | 91   process_info.version = kAwDrawGLInfoVersion; | 
|  | 92   process_info.mode = AwDrawGLInfo::kModeProcess; | 
|  | 93 | 
|  | 94   hooks_->WillProcessOnRT(functor_); | 
|  | 95   { | 
|  | 96     ScopedMakeCurrent make_current(this); | 
|  | 97     functor_->DrawGL(&process_info); | 
|  | 98   } | 
|  | 99   hooks_->DidProcessOnRT(functor_); | 
|  | 100 | 
|  | 101   if (sync) | 
|  | 102     sync->Signal(); | 
|  | 103 } | 
|  | 104 | 
|  | 105 void FakeWindow::PostInvalidate() { | 
|  | 106   CheckCurrentlyOnUIThread(); | 
|  | 107   if (on_draw_hardware_pending_) | 
|  | 108     return; | 
|  | 109   on_draw_hardware_pending_ = true; | 
|  | 110   base::MessageLoopProxy::current()->PostTask( | 
|  | 111       FROM_HERE, | 
|  | 112       base::Bind(&FakeWindow::OnDrawHardware, weak_ptr_factory_.GetWeakPtr())); | 
|  | 113 } | 
|  | 114 | 
|  | 115 void FakeWindow::OnDrawHardware() { | 
|  | 116   CheckCurrentlyOnUIThread(); | 
|  | 117   DCHECK(on_draw_hardware_pending_); | 
|  | 118   on_draw_hardware_pending_ = false; | 
|  | 119 | 
|  | 120   bool success = view_->OnDrawHardware(); | 
|  | 121   if (success) { | 
|  | 122     CreateRenderThreadIfNeeded(); | 
|  | 123 | 
|  | 124     base::WaitableEvent completion(true, false); | 
|  | 125     render_thread_loop_->PostTask( | 
|  | 126         FROM_HERE, base::Bind(&FakeWindow::DrawFunctorOnRT, | 
|  | 127                               base::Unretained(this), &completion)); | 
|  | 128     completion.Wait(); | 
|  | 129   } | 
|  | 130 } | 
|  | 131 | 
|  | 132 void FakeWindow::DrawFunctorOnRT(base::WaitableEvent* sync) { | 
|  | 133   CheckCurrentlyOnRT(); | 
|  | 134   // Ok to access UI functions until sync is signalled. | 
|  | 135   gfx::Rect location = location_; | 
|  | 136   { | 
|  | 137     AwDrawGLInfo process_info; | 
|  | 138     process_info.version = kAwDrawGLInfoVersion; | 
|  | 139     process_info.mode = AwDrawGLInfo::kModeSync; | 
|  | 140 | 
|  | 141     hooks_->WillSyncOnRT(functor_); | 
|  | 142     functor_->DrawGL(&process_info); | 
|  | 143     hooks_->DidSyncOnRT(functor_); | 
|  | 144   } | 
|  | 145   sync->Signal(); | 
|  | 146 | 
|  | 147   AwDrawGLInfo draw_info; | 
|  | 148   draw_info.version = kAwDrawGLInfoVersion; | 
|  | 149   draw_info.mode = AwDrawGLInfo::kModeDraw; | 
|  | 150   draw_info.clip_left = location.x(); | 
|  | 151   draw_info.clip_top = location.y(); | 
|  | 152   draw_info.clip_right = location.x() + location.width(); | 
|  | 153   draw_info.clip_bottom = location.y() + location.height(); | 
|  | 154   draw_info.width = surface_size_.width(); | 
|  | 155   draw_info.height = surface_size_.height(); | 
|  | 156   draw_info.is_layer = false; | 
|  | 157 | 
|  | 158   draw_info.transform[0] = 1.0; | 
|  | 159   draw_info.transform[1] = 0.0; | 
|  | 160   draw_info.transform[2] = 0.0; | 
|  | 161   draw_info.transform[3] = 0.0; | 
|  | 162 | 
|  | 163   draw_info.transform[4] = 0.0; | 
|  | 164   draw_info.transform[5] = 1.0; | 
|  | 165   draw_info.transform[6] = 0.0; | 
|  | 166   draw_info.transform[7] = 0.0; | 
|  | 167 | 
|  | 168   draw_info.transform[8] = 0.0; | 
|  | 169   draw_info.transform[9] = 0.0; | 
|  | 170   draw_info.transform[10] = 1.0; | 
|  | 171   draw_info.transform[11] = 0.0; | 
|  | 172 | 
|  | 173   draw_info.transform[12] = 0.0; | 
|  | 174   draw_info.transform[13] = 0.0; | 
|  | 175   draw_info.transform[14] = 0.0; | 
|  | 176   draw_info.transform[15] = 1.0; | 
|  | 177 | 
|  | 178   hooks_->WillDrawOnRT(functor_); | 
|  | 179   { | 
|  | 180     ScopedMakeCurrent make_current(this); | 
|  | 181     functor_->DrawGL(&draw_info); | 
|  | 182   } | 
|  | 183   hooks_->DidDrawOnRT(functor_); | 
|  | 184 } | 
|  | 185 | 
|  | 186 void FakeWindow::CheckCurrentlyOnUIThread() { | 
|  | 187   DCHECK(ui_checker_.CalledOnValidSequencedThread()); | 
|  | 188 } | 
|  | 189 | 
|  | 190 void FakeWindow::CreateRenderThreadIfNeeded() { | 
|  | 191   CheckCurrentlyOnUIThread(); | 
|  | 192   if (functor_) { | 
|  | 193     DCHECK(render_thread_.get()); | 
|  | 194     DCHECK(render_thread_loop_.get()); | 
|  | 195     return; | 
|  | 196   } | 
|  | 197   functor_ = view_->GetAwDrawGLViewContext(); | 
|  | 198   render_thread_.reset(new base::Thread("TestRenderThread")); | 
|  | 199   render_thread_->Start(); | 
|  | 200   render_thread_loop_ = render_thread_->task_runner(); | 
|  | 201   rt_checker_.DetachFromSequence(); | 
|  | 202 | 
|  | 203   base::WaitableEvent completion(true, false); | 
|  | 204   render_thread_loop_->PostTask( | 
|  | 205       FROM_HERE, base::Bind(&FakeWindow::InitializeOnRT, base::Unretained(this), | 
|  | 206                             &completion)); | 
|  | 207   completion.Wait(); | 
|  | 208 } | 
|  | 209 | 
|  | 210 void FakeWindow::InitializeOnRT(base::WaitableEvent* sync) { | 
|  | 211   CheckCurrentlyOnRT(); | 
|  | 212   surface_ = gfx::GLSurface::CreateOffscreenGLSurface(surface_size_); | 
|  | 213   DCHECK(surface_.get()); | 
|  | 214   DCHECK(surface_->GetHandle()); | 
|  | 215   context_ = gfx::GLContext::CreateGLContext(nullptr, surface_.get(), | 
|  | 216                                              gfx::PreferDiscreteGpu); | 
|  | 217   DCHECK(context_.get()); | 
|  | 218   sync->Signal(); | 
|  | 219 } | 
|  | 220 | 
|  | 221 void FakeWindow::DestroyOnRT(base::WaitableEvent* sync) { | 
|  | 222   CheckCurrentlyOnRT(); | 
|  | 223   if (context_) { | 
|  | 224     DCHECK(!context_->IsCurrent(surface_.get())); | 
|  | 225     context_ = nullptr; | 
|  | 226     surface_ = nullptr; | 
|  | 227   } | 
|  | 228   sync->Signal(); | 
|  | 229 } | 
|  | 230 | 
|  | 231 void FakeWindow::CheckCurrentlyOnRT() { | 
|  | 232   DCHECK(rt_checker_.CalledOnValidSequencedThread()); | 
|  | 233 } | 
|  | 234 | 
|  | 235 }  // namespace android_webview | 
| OLD | NEW | 
|---|