• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "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"
22 
23 const int kTestWindowWidth = 800;
24 const int kTestWindowHeight = 600;
25 
26 const int kFrameDelayMilliseconds = 16;
27 
28 const int kAnimationSteps = 240;
29 
30 const char kDisableGpu[] = "disable-gpu";
31 
32 class DemoWindow : public ui::PlatformWindowDelegate {
33  public:
DemoWindow()34   DemoWindow() : widget_(gfx::kNullAcceleratedWidget), iteration_(0) {
35     platform_window_ = ui::OzonePlatform::GetInstance()->CreatePlatformWindow(
36         this, gfx::Rect(kTestWindowWidth, kTestWindowHeight));
37   }
~DemoWindow()38   virtual ~DemoWindow() {}
39 
GetAcceleratedWidget()40   gfx::AcceleratedWidget GetAcceleratedWidget() {
41     // TODO(spang): We should start rendering asynchronously.
42     DCHECK_NE(widget_, gfx::kNullAcceleratedWidget)
43         << "Widget not available synchronously";
44     return widget_;
45   }
46 
GetSize()47   gfx::Size GetSize() { return platform_window_->GetBounds().size(); }
48 
Start()49   void Start() {
50     if (!CommandLine::ForCurrentProcess()->HasSwitch(kDisableGpu) &&
51         gfx::GLSurface::InitializeOneOff() && StartInProcessGpu() &&
52         InitializeGLSurface()) {
53       StartAnimationGL();
54     } else if (InitializeSoftwareSurface()) {
55       StartAnimationSoftware();
56     } else {
57       LOG(ERROR) << "Failed to create drawing surface";
58       Quit();
59     }
60   }
61 
Quit()62   void Quit() {
63     StopAnimation();
64     base::MessageLoop::current()->PostTask(
65         FROM_HERE, base::Bind(&base::DeletePointer<DemoWindow>, this));
66    }
67 
68   // PlatformWindowDelegate:
OnBoundsChanged(const gfx::Rect & new_bounds)69   virtual void OnBoundsChanged(const gfx::Rect& new_bounds) OVERRIDE {}
OnDamageRect(const gfx::Rect & damaged_region)70   virtual void OnDamageRect(const gfx::Rect& damaged_region) OVERRIDE {}
DispatchEvent(ui::Event * event)71   virtual void DispatchEvent(ui::Event* event) OVERRIDE {}
OnCloseRequest()72   virtual void OnCloseRequest() OVERRIDE {
73     Quit();
74   }
OnClosed()75   virtual void OnClosed() OVERRIDE {}
OnWindowStateChanged(ui::PlatformWindowState new_state)76   virtual void OnWindowStateChanged(
77       ui::PlatformWindowState new_state) OVERRIDE {}
OnLostCapture()78   virtual void OnLostCapture() OVERRIDE {}
OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget)79   virtual void OnAcceleratedWidgetAvailable(
80       gfx::AcceleratedWidget widget) OVERRIDE {
81     DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
82     widget_ = widget;
83   }
OnActivationChanged(bool active)84   virtual void OnActivationChanged(bool active) OVERRIDE {}
85 
86  private:
InitializeGLSurface()87   bool InitializeGLSurface() {
88     surface_ = gfx::GLSurface::CreateViewGLSurface(GetAcceleratedWidget());
89     if (!surface_.get()) {
90       LOG(ERROR) << "Failed to create GL surface";
91       return false;
92     }
93 
94     context_ = gfx::GLContext::CreateGLContext(
95         NULL, surface_.get(), gfx::PreferIntegratedGpu);
96     if (!context_.get()) {
97       LOG(ERROR) << "Failed to create GL context";
98       surface_ = NULL;
99       return false;
100     }
101 
102     surface_->Resize(GetSize());
103 
104     if (!context_->MakeCurrent(surface_.get())) {
105       LOG(ERROR) << "Failed to make GL context current";
106       surface_ = NULL;
107       context_ = NULL;
108       return false;
109     }
110 
111     return true;
112   }
113 
InitializeSoftwareSurface()114   bool InitializeSoftwareSurface() {
115     software_surface_ =
116         ui::SurfaceFactoryOzone::GetInstance()->CreateCanvasForWidget(
117             GetAcceleratedWidget());
118     if (!software_surface_) {
119       LOG(ERROR) << "Failed to create software surface";
120       return false;
121     }
122 
123     software_surface_->ResizeCanvas(GetSize());
124     return true;
125   }
126 
StartAnimationGL()127   void StartAnimationGL() {
128     timer_.Start(FROM_HERE,
129                  base::TimeDelta::FromMicroseconds(kFrameDelayMilliseconds),
130                  this,
131                  &DemoWindow::RenderFrameGL);
132   }
133 
StartAnimationSoftware()134   void StartAnimationSoftware() {
135     timer_.Start(FROM_HERE,
136                  base::TimeDelta::FromMicroseconds(kFrameDelayMilliseconds),
137                  this,
138                  &DemoWindow::RenderFrameSoftware);
139   }
140 
StopAnimation()141   void StopAnimation() { timer_.Stop(); }
142 
NextFraction()143   float NextFraction() {
144     float fraction = (sinf(iteration_ * 2 * M_PI / kAnimationSteps) + 1) / 2;
145 
146     iteration_++;
147     iteration_ %= kAnimationSteps;
148 
149     return fraction;
150   }
151 
RenderFrameGL()152   void RenderFrameGL() {
153     float fraction = NextFraction();
154     gfx::Size window_size = GetSize();
155 
156     glViewport(0, 0, window_size.width(), window_size.height());
157     glClearColor(1 - fraction, fraction, 0.0, 1.0);
158     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
159 
160     if (!surface_->SwapBuffers())
161       LOG(FATAL) << "Failed to swap buffers";
162   }
163 
RenderFrameSoftware()164   void RenderFrameSoftware() {
165     float fraction = NextFraction();
166     gfx::Size window_size = GetSize();
167 
168     skia::RefPtr<SkCanvas> canvas = software_surface_->GetCanvas();
169 
170     SkColor color =
171         SkColorSetARGB(0xff, 0, 0xff * fraction, 0xff * (1 - fraction));
172 
173     canvas->clear(color);
174 
175     software_surface_->PresentCanvas(gfx::Rect(window_size));
176   }
177 
StartInProcessGpu()178   bool StartInProcessGpu() { return ui_thread_gpu_.Initialize(); }
179 
180   // Timer for animation.
181   base::RepeatingTimer<DemoWindow> timer_;
182 
183   // Bits for GL rendering.
184   scoped_refptr<gfx::GLSurface> surface_;
185   scoped_refptr<gfx::GLContext> context_;
186 
187   // Bits for software rendeirng.
188   scoped_ptr<ui::SurfaceOzoneCanvas> software_surface_;
189 
190   // Window-related state.
191   scoped_ptr<ui::PlatformWindow> platform_window_;
192   gfx::AcceleratedWidget widget_;
193 
194   // Helper for applications that do GL on main thread.
195   ui::UiThreadGpu ui_thread_gpu_;
196 
197   // Animation state.
198   int iteration_;
199 
200   DISALLOW_COPY_AND_ASSIGN(DemoWindow);
201 };
202 
main(int argc,char ** argv)203 int main(int argc, char** argv) {
204   CommandLine::Init(argc, argv);
205   base::AtExitManager exit_manager;
206 
207   // Build UI thread message loop. This is used by platform
208   // implementations for event polling & running background tasks.
209   base::MessageLoopForUI message_loop;
210 
211   ui::OzonePlatform::InitializeForUI();
212 
213   DemoWindow* window = new DemoWindow;
214   window->Start();
215 
216   // Run the message loop until there's nothing left to do.
217   // TODO(spang): Should we use QuitClosure instead?
218   base::RunLoop run_loop;
219   run_loop.RunUntilIdle();
220 
221   return 0;
222 }
223