| Index: android_webview/browser/test/fake_window.cc | 
| diff --git a/android_webview/browser/test/fake_window.cc b/android_webview/browser/test/fake_window.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..c709f62e85f8225fd7533f616fc49dad9ed8a0a6 | 
| --- /dev/null | 
| +++ b/android_webview/browser/test/fake_window.cc | 
| @@ -0,0 +1,235 @@ | 
| +// Copyright 2014 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "android_webview/browser/test/fake_window.h" | 
| + | 
| +#include "android_webview/browser/browser_view_renderer.h" | 
| +#include "android_webview/public/browser/draw_gl.h" | 
| +#include "base/message_loop/message_loop_proxy.h" | 
| +#include "base/synchronization/waitable_event.h" | 
| +#include "base/threading/thread.h" | 
| +#include "ui/gl/gl_bindings.h" | 
| + | 
| +namespace android_webview { | 
| + | 
| +class FakeWindow::ScopedMakeCurrent { | 
| + public: | 
| +  ScopedMakeCurrent(FakeWindow* view_root) : view_root_(view_root) { | 
| +    DCHECK(!view_root_->context_current_); | 
| +    view_root_->context_current_ = true; | 
| +    bool result = view_root_->context_->MakeCurrent(view_root_->surface_.get()); | 
| +    DCHECK(result); | 
| +  }; | 
| + | 
| +  ~ScopedMakeCurrent() { | 
| +    DCHECK(view_root_->context_current_); | 
| +    view_root_->context_current_ = false; | 
| + | 
| +    // Release the underlying EGLContext. This is required because the real | 
| +    // GLContextEGL may no longer be current here and to satisfy DCHECK in | 
| +    // GLContextEGL::IsCurrent. | 
| +    eglMakeCurrent(view_root_->surface_->GetDisplay(), EGL_NO_SURFACE, | 
| +                   EGL_NO_SURFACE, EGL_NO_CONTEXT); | 
| +    view_root_->context_->ReleaseCurrent(view_root_->surface_.get()); | 
| +  } | 
| + | 
| + private: | 
| +  FakeWindow* view_root_; | 
| +}; | 
| + | 
| +FakeWindow::FakeWindow(BrowserViewRenderer* view, | 
| +                       WindowHooks* hooks, | 
| +                       gfx::Rect location) | 
| +    : view_(view), | 
| +      hooks_(hooks), | 
| +      surface_size_(100, 100), | 
| +      location_(location), | 
| +      on_draw_hardware_pending_(false), | 
| +      functor_(nullptr), | 
| +      context_current_(false), | 
| +      weak_ptr_factory_(this) { | 
| +  CheckCurrentlyOnUIThread(); | 
| +  DCHECK(view_); | 
| +  view_->OnAttachedToWindow(location_.width(), location_.height()); | 
| +} | 
| + | 
| +FakeWindow::~FakeWindow() { | 
| +  CheckCurrentlyOnUIThread(); | 
| +} | 
| + | 
| +void FakeWindow::Detach() { | 
| +  CheckCurrentlyOnUIThread(); | 
| +  view_->OnDetachedFromWindow(); | 
| + | 
| +  if (render_thread_loop_) { | 
| +    base::WaitableEvent completion(true, false); | 
| +    render_thread_loop_->PostTask( | 
| +        FROM_HERE, base::Bind(&FakeWindow::DestroyOnRT, base::Unretained(this), | 
| +                              &completion)); | 
| +    completion.Wait(); | 
| +  } | 
| + | 
| +  render_thread_.reset(); | 
| +  functor_ = nullptr; | 
| +} | 
| + | 
| +void FakeWindow::RequestDrawGL(bool wait_for_completion) { | 
| +  CheckCurrentlyOnUIThread(); | 
| +  base::WaitableEvent completion(true, false); | 
| +  render_thread_loop_->PostTask( | 
| +      FROM_HERE, | 
| +      base::Bind(&FakeWindow::ProcessFunctorOnRT, base::Unretained(this), | 
| +                 wait_for_completion ? &completion : nullptr)); | 
| +  if (wait_for_completion) | 
| +    completion.Wait(); | 
| +} | 
| + | 
| +void FakeWindow::ProcessFunctorOnRT(base::WaitableEvent* sync) { | 
| +  CheckCurrentlyOnRT(); | 
| +  AwDrawGLInfo process_info; | 
| +  process_info.version = kAwDrawGLInfoVersion; | 
| +  process_info.mode = AwDrawGLInfo::kModeProcess; | 
| + | 
| +  hooks_->WillProcessOnRT(functor_); | 
| +  { | 
| +    ScopedMakeCurrent make_current(this); | 
| +    functor_->DrawGL(&process_info); | 
| +  } | 
| +  hooks_->DidProcessOnRT(functor_); | 
| + | 
| +  if (sync) | 
| +    sync->Signal(); | 
| +} | 
| + | 
| +void FakeWindow::PostInvalidate() { | 
| +  CheckCurrentlyOnUIThread(); | 
| +  if (on_draw_hardware_pending_) | 
| +    return; | 
| +  on_draw_hardware_pending_ = true; | 
| +  base::MessageLoopProxy::current()->PostTask( | 
| +      FROM_HERE, | 
| +      base::Bind(&FakeWindow::OnDrawHardware, weak_ptr_factory_.GetWeakPtr())); | 
| +} | 
| + | 
| +void FakeWindow::OnDrawHardware() { | 
| +  CheckCurrentlyOnUIThread(); | 
| +  DCHECK(on_draw_hardware_pending_); | 
| +  on_draw_hardware_pending_ = false; | 
| + | 
| +  bool success = view_->OnDrawHardware(); | 
| +  if (success) { | 
| +    CreateRenderThreadIfNeeded(); | 
| + | 
| +    base::WaitableEvent completion(true, false); | 
| +    render_thread_loop_->PostTask( | 
| +        FROM_HERE, base::Bind(&FakeWindow::DrawFunctorOnRT, | 
| +                              base::Unretained(this), &completion)); | 
| +    completion.Wait(); | 
| +  } | 
| +} | 
| + | 
| +void FakeWindow::DrawFunctorOnRT(base::WaitableEvent* sync) { | 
| +  CheckCurrentlyOnRT(); | 
| +  // Ok to access UI functions until sync is signalled. | 
| +  gfx::Rect location = location_; | 
| +  { | 
| +    AwDrawGLInfo process_info; | 
| +    process_info.version = kAwDrawGLInfoVersion; | 
| +    process_info.mode = AwDrawGLInfo::kModeSync; | 
| + | 
| +    hooks_->WillSyncOnRT(functor_); | 
| +    functor_->DrawGL(&process_info); | 
| +    hooks_->DidSyncOnRT(functor_); | 
| +  } | 
| +  sync->Signal(); | 
| + | 
| +  AwDrawGLInfo draw_info; | 
| +  draw_info.version = kAwDrawGLInfoVersion; | 
| +  draw_info.mode = AwDrawGLInfo::kModeDraw; | 
| +  draw_info.clip_left = location.x(); | 
| +  draw_info.clip_top = location.y(); | 
| +  draw_info.clip_right = location.x() + location.width(); | 
| +  draw_info.clip_bottom = location.y() + location.height(); | 
| +  draw_info.width = surface_size_.width(); | 
| +  draw_info.height = surface_size_.height(); | 
| +  draw_info.is_layer = false; | 
| + | 
| +  draw_info.transform[0] = 1.0; | 
| +  draw_info.transform[1] = 0.0; | 
| +  draw_info.transform[2] = 0.0; | 
| +  draw_info.transform[3] = 0.0; | 
| + | 
| +  draw_info.transform[4] = 0.0; | 
| +  draw_info.transform[5] = 1.0; | 
| +  draw_info.transform[6] = 0.0; | 
| +  draw_info.transform[7] = 0.0; | 
| + | 
| +  draw_info.transform[8] = 0.0; | 
| +  draw_info.transform[9] = 0.0; | 
| +  draw_info.transform[10] = 1.0; | 
| +  draw_info.transform[11] = 0.0; | 
| + | 
| +  draw_info.transform[12] = 0.0; | 
| +  draw_info.transform[13] = 0.0; | 
| +  draw_info.transform[14] = 0.0; | 
| +  draw_info.transform[15] = 1.0; | 
| + | 
| +  hooks_->WillDrawOnRT(functor_); | 
| +  { | 
| +    ScopedMakeCurrent make_current(this); | 
| +    functor_->DrawGL(&draw_info); | 
| +  } | 
| +  hooks_->DidDrawOnRT(functor_); | 
| +} | 
| + | 
| +void FakeWindow::CheckCurrentlyOnUIThread() { | 
| +  DCHECK(ui_checker_.CalledOnValidSequencedThread()); | 
| +} | 
| + | 
| +void FakeWindow::CreateRenderThreadIfNeeded() { | 
| +  CheckCurrentlyOnUIThread(); | 
| +  if (functor_) { | 
| +    DCHECK(render_thread_.get()); | 
| +    DCHECK(render_thread_loop_.get()); | 
| +    return; | 
| +  } | 
| +  functor_ = view_->GetAwDrawGLViewContext(); | 
| +  render_thread_.reset(new base::Thread("TestRenderThread")); | 
| +  render_thread_->Start(); | 
| +  render_thread_loop_ = render_thread_->task_runner(); | 
| +  rt_checker_.DetachFromSequence(); | 
| + | 
| +  base::WaitableEvent completion(true, false); | 
| +  render_thread_loop_->PostTask( | 
| +      FROM_HERE, base::Bind(&FakeWindow::InitializeOnRT, base::Unretained(this), | 
| +                            &completion)); | 
| +  completion.Wait(); | 
| +} | 
| + | 
| +void FakeWindow::InitializeOnRT(base::WaitableEvent* sync) { | 
| +  CheckCurrentlyOnRT(); | 
| +  surface_ = gfx::GLSurface::CreateOffscreenGLSurface(surface_size_); | 
| +  DCHECK(surface_.get()); | 
| +  DCHECK(surface_->GetHandle()); | 
| +  context_ = gfx::GLContext::CreateGLContext(nullptr, surface_.get(), | 
| +                                             gfx::PreferDiscreteGpu); | 
| +  DCHECK(context_.get()); | 
| +  sync->Signal(); | 
| +} | 
| + | 
| +void FakeWindow::DestroyOnRT(base::WaitableEvent* sync) { | 
| +  CheckCurrentlyOnRT(); | 
| +  if (context_) { | 
| +    DCHECK(!context_->IsCurrent(surface_.get())); | 
| +    context_ = nullptr; | 
| +    surface_ = nullptr; | 
| +  } | 
| +  sync->Signal(); | 
| +} | 
| + | 
| +void FakeWindow::CheckCurrentlyOnRT() { | 
| +  DCHECK(rt_checker_.CalledOnValidSequencedThread()); | 
| +} | 
| + | 
| +}  // namespace android_webview | 
|  |