| 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
|
|
|