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.
5 #include "android_webview/browser/test/fake_window.h"
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"
14 namespace android_webview
{
16 class FakeWindow::ScopedMakeCurrent
{
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());
25 ~ScopedMakeCurrent() {
26 DCHECK(view_root_
->context_current_
);
27 view_root_
->context_current_
= false;
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());
38 FakeWindow
* view_root_
;
41 FakeWindow::FakeWindow(BrowserViewRenderer
* view
,
46 surface_size_(100, 100),
48 on_draw_hardware_pending_(false),
50 context_current_(false),
51 weak_ptr_factory_(this) {
52 CheckCurrentlyOnUIThread();
54 view_
->OnAttachedToWindow(location_
.width(), location_
.height());
55 view_
->SetWindowVisibility(true);
56 view_
->SetViewVisibility(true);
59 FakeWindow::~FakeWindow() {
60 CheckCurrentlyOnUIThread();
63 void FakeWindow::Detach() {
64 CheckCurrentlyOnUIThread();
65 view_
->OnDetachedFromWindow();
67 if (render_thread_loop_
) {
68 base::WaitableEvent
completion(true, false);
69 render_thread_loop_
->PostTask(
70 FROM_HERE
, base::Bind(&FakeWindow::DestroyOnRT
, base::Unretained(this),
75 render_thread_
.reset();
79 void FakeWindow::RequestDrawGL(bool wait_for_completion
) {
80 CheckCurrentlyOnUIThread();
81 base::WaitableEvent
completion(true, false);
82 render_thread_loop_
->PostTask(
84 base::Bind(&FakeWindow::ProcessFunctorOnRT
, base::Unretained(this),
85 wait_for_completion
? &completion
: nullptr));
86 if (wait_for_completion
)
90 void FakeWindow::ProcessFunctorOnRT(base::WaitableEvent
* sync
) {
92 AwDrawGLInfo process_info
;
93 process_info
.version
= kAwDrawGLInfoVersion
;
94 process_info
.mode
= AwDrawGLInfo::kModeProcess
;
96 hooks_
->WillProcessOnRT(functor_
);
98 ScopedMakeCurrent
make_current(this);
99 functor_
->DrawGL(&process_info
);
101 hooks_
->DidProcessOnRT(functor_
);
107 void FakeWindow::PostInvalidate() {
108 CheckCurrentlyOnUIThread();
109 if (on_draw_hardware_pending_
)
111 on_draw_hardware_pending_
= true;
112 base::MessageLoopProxy::current()->PostTask(
114 base::Bind(&FakeWindow::OnDrawHardware
, weak_ptr_factory_
.GetWeakPtr()));
117 void FakeWindow::OnDrawHardware() {
118 CheckCurrentlyOnUIThread();
119 DCHECK(on_draw_hardware_pending_
);
120 on_draw_hardware_pending_
= false;
122 hooks_
->WillOnDraw();
123 bool success
= view_
->OnDrawHardware();
124 hooks_
->DidOnDraw(success
);
126 CreateRenderThreadIfNeeded();
128 base::WaitableEvent
completion(true, false);
129 render_thread_loop_
->PostTask(
130 FROM_HERE
, base::Bind(&FakeWindow::DrawFunctorOnRT
,
131 base::Unretained(this), &completion
));
136 void FakeWindow::DrawFunctorOnRT(base::WaitableEvent
* sync
) {
137 CheckCurrentlyOnRT();
138 // Ok to access UI functions until sync is signalled.
139 gfx::Rect location
= location_
;
141 AwDrawGLInfo process_info
;
142 process_info
.version
= kAwDrawGLInfoVersion
;
143 process_info
.mode
= AwDrawGLInfo::kModeSync
;
145 hooks_
->WillSyncOnRT(functor_
);
146 functor_
->DrawGL(&process_info
);
147 hooks_
->DidSyncOnRT(functor_
);
151 AwDrawGLInfo draw_info
;
152 draw_info
.version
= kAwDrawGLInfoVersion
;
153 draw_info
.mode
= AwDrawGLInfo::kModeDraw
;
154 draw_info
.clip_left
= location
.x();
155 draw_info
.clip_top
= location
.y();
156 draw_info
.clip_right
= location
.x() + location
.width();
157 draw_info
.clip_bottom
= location
.y() + location
.height();
158 draw_info
.width
= surface_size_
.width();
159 draw_info
.height
= surface_size_
.height();
160 draw_info
.is_layer
= false;
162 draw_info
.transform
[0] = 1.0;
163 draw_info
.transform
[1] = 0.0;
164 draw_info
.transform
[2] = 0.0;
165 draw_info
.transform
[3] = 0.0;
167 draw_info
.transform
[4] = 0.0;
168 draw_info
.transform
[5] = 1.0;
169 draw_info
.transform
[6] = 0.0;
170 draw_info
.transform
[7] = 0.0;
172 draw_info
.transform
[8] = 0.0;
173 draw_info
.transform
[9] = 0.0;
174 draw_info
.transform
[10] = 1.0;
175 draw_info
.transform
[11] = 0.0;
177 draw_info
.transform
[12] = 0.0;
178 draw_info
.transform
[13] = 0.0;
179 draw_info
.transform
[14] = 0.0;
180 draw_info
.transform
[15] = 1.0;
182 hooks_
->WillDrawOnRT(functor_
);
184 ScopedMakeCurrent
make_current(this);
185 functor_
->DrawGL(&draw_info
);
187 hooks_
->DidDrawOnRT(functor_
);
190 void FakeWindow::CheckCurrentlyOnUIThread() {
191 DCHECK(ui_checker_
.CalledOnValidSequencedThread());
194 void FakeWindow::CreateRenderThreadIfNeeded() {
195 CheckCurrentlyOnUIThread();
197 DCHECK(render_thread_
.get());
198 DCHECK(render_thread_loop_
.get());
201 functor_
= view_
->GetAwDrawGLViewContext();
202 render_thread_
.reset(new base::Thread("TestRenderThread"));
203 render_thread_
->Start();
204 render_thread_loop_
= render_thread_
->task_runner();
205 rt_checker_
.DetachFromSequence();
207 base::WaitableEvent
completion(true, false);
208 render_thread_loop_
->PostTask(
209 FROM_HERE
, base::Bind(&FakeWindow::InitializeOnRT
, base::Unretained(this),
214 void FakeWindow::InitializeOnRT(base::WaitableEvent
* sync
) {
215 CheckCurrentlyOnRT();
216 surface_
= gfx::GLSurface::CreateOffscreenGLSurface(surface_size_
);
217 DCHECK(surface_
.get());
218 DCHECK(surface_
->GetHandle());
219 context_
= gfx::GLContext::CreateGLContext(nullptr, surface_
.get(),
220 gfx::PreferDiscreteGpu
);
221 DCHECK(context_
.get());
225 void FakeWindow::DestroyOnRT(base::WaitableEvent
* sync
) {
226 CheckCurrentlyOnRT();
228 DCHECK(!context_
->IsCurrent(surface_
.get()));
235 void FakeWindow::CheckCurrentlyOnRT() {
236 DCHECK(rt_checker_
.CalledOnValidSequencedThread());
239 } // namespace android_webview