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 "base/at_exit.h"
6 #include "base/command_line.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/run_loop.h"
9 #include "base/timer/timer.h"
10 #include "third_party/skia/include/core/SkCanvas.h"
11 #include "third_party/skia/include/core/SkColor.h"
12 #include "ui/gfx/geometry/size.h"
13 #include "ui/gl/gl_bindings.h"
14 #include "ui/gl/gl_context.h"
15 #include "ui/gl/gl_surface.h"
16 #include "ui/ozone/public/ozone_platform.h"
17 #include "ui/ozone/public/surface_factory_ozone.h"
18 #include "ui/ozone/public/surface_ozone_canvas.h"
19 #include "ui/ozone/public/ui_thread_gpu.h"
20 #include "ui/platform_window/platform_window.h"
21 #include "ui/platform_window/platform_window_delegate.h"
23 const int kTestWindowWidth
= 800;
24 const int kTestWindowHeight
= 600;
26 const int kFrameDelayMilliseconds
= 16;
28 const int kAnimationSteps
= 240;
30 const char kDisableGpu
[] = "disable-gpu";
32 class DemoWindow
: public ui::PlatformWindowDelegate
{
34 DemoWindow() : widget_(gfx::kNullAcceleratedWidget
), iteration_(0) {
35 platform_window_
= ui::OzonePlatform::GetInstance()->CreatePlatformWindow(
36 this, gfx::Rect(kTestWindowWidth
, kTestWindowHeight
));
38 ~DemoWindow() override
{}
40 gfx::AcceleratedWidget
GetAcceleratedWidget() {
41 // TODO(spang): We should start rendering asynchronously.
42 DCHECK_NE(widget_
, gfx::kNullAcceleratedWidget
)
43 << "Widget not available synchronously";
47 gfx::Size
GetSize() { return platform_window_
->GetBounds().size(); }
50 if (!CommandLine::ForCurrentProcess()->HasSwitch(kDisableGpu
) &&
51 gfx::GLSurface::InitializeOneOff() && StartInProcessGpu() &&
52 InitializeGLSurface()) {
54 } else if (InitializeSoftwareSurface()) {
55 StartAnimationSoftware();
57 LOG(ERROR
) << "Failed to create drawing surface";
64 base::MessageLoop::current()->PostTask(
65 FROM_HERE
, base::Bind(&base::DeletePointer
<DemoWindow
>, this));
68 // PlatformWindowDelegate:
69 void OnBoundsChanged(const gfx::Rect
& new_bounds
) override
{}
70 void OnDamageRect(const gfx::Rect
& damaged_region
) override
{}
71 void DispatchEvent(ui::Event
* event
) override
{}
72 void OnCloseRequest() override
{ Quit(); }
73 void OnClosed() override
{}
74 void OnWindowStateChanged(ui::PlatformWindowState new_state
) override
{}
75 void OnLostCapture() override
{}
76 void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget
) override
{
77 DCHECK_NE(widget
, gfx::kNullAcceleratedWidget
);
80 void OnActivationChanged(bool active
) override
{}
83 bool InitializeGLSurface() {
84 surface_
= gfx::GLSurface::CreateViewGLSurface(GetAcceleratedWidget());
85 if (!surface_
.get()) {
86 LOG(ERROR
) << "Failed to create GL surface";
90 context_
= gfx::GLContext::CreateGLContext(
91 NULL
, surface_
.get(), gfx::PreferIntegratedGpu
);
92 if (!context_
.get()) {
93 LOG(ERROR
) << "Failed to create GL context";
98 surface_
->Resize(GetSize());
100 if (!context_
->MakeCurrent(surface_
.get())) {
101 LOG(ERROR
) << "Failed to make GL context current";
110 bool InitializeSoftwareSurface() {
112 ui::SurfaceFactoryOzone::GetInstance()->CreateCanvasForWidget(
113 GetAcceleratedWidget());
114 if (!software_surface_
) {
115 LOG(ERROR
) << "Failed to create software surface";
119 software_surface_
->ResizeCanvas(GetSize());
123 void StartAnimationGL() {
124 timer_
.Start(FROM_HERE
,
125 base::TimeDelta::FromMicroseconds(kFrameDelayMilliseconds
),
127 &DemoWindow::RenderFrameGL
);
130 void StartAnimationSoftware() {
131 timer_
.Start(FROM_HERE
,
132 base::TimeDelta::FromMicroseconds(kFrameDelayMilliseconds
),
134 &DemoWindow::RenderFrameSoftware
);
137 void StopAnimation() { timer_
.Stop(); }
139 float NextFraction() {
140 float fraction
= (sinf(iteration_
* 2 * M_PI
/ kAnimationSteps
) + 1) / 2;
143 iteration_
%= kAnimationSteps
;
148 void RenderFrameGL() {
149 float fraction
= NextFraction();
150 gfx::Size window_size
= GetSize();
152 glViewport(0, 0, window_size
.width(), window_size
.height());
153 glClearColor(1 - fraction
, fraction
, 0.0, 1.0);
154 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
156 if (!surface_
->SwapBuffers())
157 LOG(FATAL
) << "Failed to swap buffers";
160 void RenderFrameSoftware() {
161 float fraction
= NextFraction();
162 gfx::Size window_size
= GetSize();
164 skia::RefPtr
<SkCanvas
> canvas
= software_surface_
->GetCanvas();
167 SkColorSetARGB(0xff, 0, 0xff * fraction
, 0xff * (1 - fraction
));
169 canvas
->clear(color
);
171 software_surface_
->PresentCanvas(gfx::Rect(window_size
));
174 bool StartInProcessGpu() { return ui_thread_gpu_
.Initialize(); }
176 // Timer for animation.
177 base::RepeatingTimer
<DemoWindow
> timer_
;
179 // Bits for GL rendering.
180 scoped_refptr
<gfx::GLSurface
> surface_
;
181 scoped_refptr
<gfx::GLContext
> context_
;
183 // Bits for software rendeirng.
184 scoped_ptr
<ui::SurfaceOzoneCanvas
> software_surface_
;
186 // Window-related state.
187 scoped_ptr
<ui::PlatformWindow
> platform_window_
;
188 gfx::AcceleratedWidget widget_
;
190 // Helper for applications that do GL on main thread.
191 ui::UiThreadGpu ui_thread_gpu_
;
196 DISALLOW_COPY_AND_ASSIGN(DemoWindow
);
199 int main(int argc
, char** argv
) {
200 CommandLine::Init(argc
, argv
);
201 base::AtExitManager exit_manager
;
203 // Build UI thread message loop. This is used by platform
204 // implementations for event polling & running background tasks.
205 base::MessageLoopForUI message_loop
;
207 ui::OzonePlatform::InitializeForUI();
209 DemoWindow
* window
= new DemoWindow
;
212 // Run the message loop until there's nothing left to do.
213 // TODO(spang): Should we use QuitClosure instead?
214 base::RunLoop run_loop
;
215 run_loop
.RunUntilIdle();