- add sources.
[platform/framework/web/crosswalk.git] / src / ui / aura / bench / bench_main.cc
1 // Copyright (c) 2012 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/bind.h"
7 #include "base/command_line.h"
8 #include "base/i18n/icu_util.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/string_split.h"
12 #include "base/time/time.h"
13 #include "cc/output/context_provider.h"
14 #include "third_party/khronos/GLES2/gl2.h"
15 #include "third_party/skia/include/core/SkXfermode.h"
16 #include "ui/aura/client/default_capture_client.h"
17 #include "ui/aura/env.h"
18 #include "ui/aura/root_window.h"
19 #include "ui/aura/test/test_focus_client.h"
20 #include "ui/aura/test/test_screen.h"
21 #include "ui/aura/window.h"
22 #include "ui/base/hit_test.h"
23 #include "ui/base/resource/resource_bundle.h"
24 #include "ui/base/ui_base_paths.h"
25 #include "ui/compositor/compositor.h"
26 #include "ui/compositor/compositor_observer.h"
27 #include "ui/compositor/debug_utils.h"
28 #include "ui/compositor/layer.h"
29 #include "ui/compositor/test/context_factories_for_test.h"
30 #include "ui/gfx/canvas.h"
31 #include "ui/gfx/rect.h"
32 #include "ui/gfx/skia_util.h"
33 #ifndef GL_GLEXT_PROTOTYPES
34 #define GL_GLEXT_PROTOTYPES 1
35 #endif
36 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
37 #include "third_party/khronos/GLES2/gl2ext.h"
38
39 #if defined(USE_X11)
40 #include "base/message_loop/message_pump_x11.h"
41 #endif
42
43 using base::TimeTicks;
44 using ui::Compositor;
45 using ui::Layer;
46 using ui::LayerDelegate;
47 using WebKit::WebGraphicsContext3D;
48
49 namespace {
50
51 class ColoredLayer : public Layer, public LayerDelegate {
52  public:
53   explicit ColoredLayer(SkColor color)
54       : Layer(ui::LAYER_TEXTURED),
55         color_(color),
56         draw_(true) {
57     set_delegate(this);
58   }
59
60   virtual ~ColoredLayer() {}
61
62   // Overridden from LayerDelegate:
63   virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
64     if (draw_) {
65       canvas->DrawColor(color_);
66     }
67   }
68
69   virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
70   }
71
72   virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
73     return base::Closure();
74   }
75
76   void set_color(SkColor color) { color_ = color; }
77   void set_draw(bool draw) { draw_ = draw; }
78
79  private:
80   SkColor color_;
81   bool draw_;
82
83   DISALLOW_COPY_AND_ASSIGN(ColoredLayer);
84 };
85
86 const int kFrames = 100;
87
88 // Benchmark base class, hooks up drawing callback and displaying FPS.
89 class BenchCompositorObserver : public ui::CompositorObserver {
90  public:
91   explicit BenchCompositorObserver(int max_frames)
92       : start_time_(),
93         frames_(0),
94         max_frames_(max_frames) {
95   }
96
97   virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE {}
98
99   virtual void OnCompositingStarted(Compositor* compositor,
100                                     base::TimeTicks start_time) OVERRIDE {}
101
102   virtual void OnCompositingEnded(Compositor* compositor) OVERRIDE {
103     if (start_time_.is_null()) {
104       start_time_ = TimeTicks::Now();
105     } else {
106       ++frames_;
107       if (frames_ % kFrames == 0) {
108         TimeTicks now = TimeTicks::Now();
109         double ms = (now - start_time_).InMillisecondsF() / kFrames;
110         LOG(INFO) << "FPS: " << 1000.f / ms << " (" << ms << " ms)";
111         start_time_ = now;
112       }
113     }
114     if (max_frames_ && frames_ == max_frames_) {
115       base::MessageLoop::current()->Quit();
116     } else {
117       Draw();
118     }
119   }
120
121   virtual void OnCompositingAborted(Compositor* compositor) OVERRIDE {}
122
123   virtual void OnCompositingLockStateChanged(
124       Compositor* compositor) OVERRIDE {}
125
126   virtual void OnUpdateVSyncParameters(ui::Compositor* compositor,
127                                        base::TimeTicks timebase,
128                                        base::TimeDelta interval) OVERRIDE {
129   }
130
131   virtual void Draw() {}
132
133   int frames() const { return frames_; }
134
135  private:
136   TimeTicks start_time_;
137   int frames_;
138   int max_frames_;
139
140   DISALLOW_COPY_AND_ASSIGN(BenchCompositorObserver);
141 };
142
143 class WebGLTexture : public ui::Texture {
144  public:
145   WebGLTexture(WebGraphicsContext3D* context, const gfx::Size& size)
146       : ui::Texture(false, size, 1.0f),
147         context_(context),
148         texture_id_(context_->createTexture()) {
149     context_->bindTexture(GL_TEXTURE_2D, texture_id_);
150     context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
151     context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
152     context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
153     context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
154     context_->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
155                          size.width(), size.height(), 0,
156                          GL_RGBA, GL_UNSIGNED_BYTE, NULL);
157   }
158
159   virtual unsigned int PrepareTexture() OVERRIDE {
160     return texture_id_;
161   }
162
163   virtual WebGraphicsContext3D* HostContext3D() OVERRIDE {
164     return context_;
165   }
166
167  private:
168   virtual ~WebGLTexture() {
169     context_->deleteTexture(texture_id_);
170   }
171
172   WebGraphicsContext3D* context_;
173   unsigned texture_id_;
174
175   DISALLOW_COPY_AND_ASSIGN(WebGLTexture);
176 };
177
178 // A benchmark that adds a texture layer that is updated every frame.
179 class WebGLBench : public BenchCompositorObserver {
180  public:
181   WebGLBench(Layer* parent, Compositor* compositor, int max_frames)
182       : BenchCompositorObserver(max_frames),
183         parent_(parent),
184         webgl_(ui::LAYER_TEXTURED),
185         compositor_(compositor),
186         texture_(),
187         fbo_(0),
188         do_draw_(true) {
189     CommandLine* command_line = CommandLine::ForCurrentProcess();
190     do_draw_ = !command_line->HasSwitch("disable-draw");
191
192     std::string webgl_size = command_line->GetSwitchValueASCII("webgl-size");
193     int width = 0;
194     int height = 0;
195     if (!webgl_size.empty()) {
196       std::vector<std::string> split_size;
197       base::SplitString(webgl_size, 'x', &split_size);
198       if (split_size.size() == 2) {
199         width = atoi(split_size[0].c_str());
200         height = atoi(split_size[1].c_str());
201       }
202     }
203     if (!width || !height) {
204       width = 800;
205       height = 600;
206     }
207     gfx::Rect bounds(width, height);
208     webgl_.SetBounds(bounds);
209     parent_->Add(&webgl_);
210
211     context_provider_ =
212         ui::ContextFactory::GetInstance()->SharedMainThreadContextProvider();
213     WebKit::WebGraphicsContext3D* context = context_provider_->Context3d();
214     context->makeContextCurrent();
215     texture_ = new WebGLTexture(context, bounds.size());
216     fbo_ = context->createFramebuffer();
217     compositor->AddObserver(this);
218     webgl_.SetExternalTexture(texture_.get());
219     context->bindFramebuffer(GL_FRAMEBUFFER, fbo_);
220     context->framebufferTexture2D(
221         GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
222         GL_TEXTURE_2D, texture_->PrepareTexture(), 0);
223     context->clearColor(0.f, 1.f, 0.f, 1.f);
224     context->clear(GL_COLOR_BUFFER_BIT);
225     context->flush();
226   }
227
228   virtual ~WebGLBench() {
229     context_provider_->Context3d()->makeContextCurrent();
230     context_provider_->Context3d()->deleteFramebuffer(fbo_);
231     webgl_.SetShowPaintedContent();
232     texture_ = NULL;
233     compositor_->RemoveObserver(this);
234   }
235
236   virtual void Draw() OVERRIDE {
237     if (do_draw_) {
238       WebKit::WebGraphicsContext3D* context = context_provider_->Context3d();
239       context->makeContextCurrent();
240       context->clearColor((frames() % kFrames)*1.0/kFrames, 1.f, 0.f, 1.f);
241       context->clear(GL_COLOR_BUFFER_BIT);
242       context->flush();
243     }
244     webgl_.SetExternalTexture(texture_.get());
245     webgl_.SchedulePaint(gfx::Rect(webgl_.bounds().size()));
246     compositor_->ScheduleDraw();
247   }
248
249  private:
250   Layer* parent_;
251   Layer webgl_;
252   Compositor* compositor_;
253   scoped_refptr<cc::ContextProvider> context_provider_;
254   scoped_refptr<WebGLTexture> texture_;
255
256   // The FBO that is used to render to the texture.
257   unsigned int fbo_;
258
259   // Whether or not to draw to the texture every frame.
260   bool do_draw_;
261
262   DISALLOW_COPY_AND_ASSIGN(WebGLBench);
263 };
264
265 // A benchmark that paints (in software) all tiles every frame.
266 class SoftwareScrollBench : public BenchCompositorObserver {
267  public:
268   SoftwareScrollBench(ColoredLayer* layer,
269                       Compositor* compositor,
270                       int max_frames)
271       : BenchCompositorObserver(max_frames),
272         layer_(layer),
273         compositor_(compositor) {
274     compositor->AddObserver(this);
275     layer_->set_draw(
276         !CommandLine::ForCurrentProcess()->HasSwitch("disable-draw"));
277   }
278
279   virtual ~SoftwareScrollBench() {
280     compositor_->RemoveObserver(this);
281   }
282
283   virtual void Draw() OVERRIDE {
284     layer_->set_color(
285         SkColorSetARGBInline(255*(frames() % kFrames)/kFrames, 255, 0, 255));
286     layer_->SchedulePaint(gfx::Rect(layer_->bounds().size()));
287   }
288
289  private:
290   ColoredLayer* layer_;
291   Compositor* compositor_;
292
293   DISALLOW_COPY_AND_ASSIGN(SoftwareScrollBench);
294 };
295
296 }  // namespace
297
298 int main(int argc, char** argv) {
299   CommandLine::Init(argc, argv);
300
301   base::AtExitManager exit_manager;
302
303   // The ContextFactory must exist before any Compositors are created.
304   bool allow_test_contexts = false;
305   ui::InitializeContextFactoryForTests(allow_test_contexts);
306
307   ui::RegisterPathProvider();
308   base::i18n::InitializeICU();
309   ResourceBundle::InitSharedInstanceWithLocale("en-US", NULL);
310
311   base::MessageLoop message_loop(base::MessageLoop::TYPE_UI);
312   aura::Env::CreateInstance();
313   scoped_ptr<aura::TestScreen> test_screen(
314       aura::TestScreen::CreateFullscreen());
315   gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen.get());
316   scoped_ptr<aura::RootWindow> root_window(
317       test_screen->CreateRootWindowForPrimaryDisplay());
318   aura::client::SetCaptureClient(
319       root_window.get(),
320       new aura::client::DefaultCaptureClient(root_window.get()));
321
322   scoped_ptr<aura::client::FocusClient> focus_client(
323       new aura::test::TestFocusClient);
324   aura::client::SetFocusClient(root_window.get(), focus_client.get());
325
326   // add layers
327   ColoredLayer background(SK_ColorRED);
328   background.SetBounds(root_window->bounds());
329   root_window->layer()->Add(&background);
330
331   ColoredLayer window(SK_ColorBLUE);
332   window.SetBounds(gfx::Rect(background.bounds().size()));
333   background.Add(&window);
334
335   Layer content_layer(ui::LAYER_NOT_DRAWN);
336
337   CommandLine* command_line = CommandLine::ForCurrentProcess();
338   bool force = command_line->HasSwitch("force-render-surface");
339   content_layer.SetForceRenderSurface(force);
340   gfx::Rect bounds(window.bounds().size());
341   bounds.Inset(0, 30, 0, 0);
342   content_layer.SetBounds(bounds);
343   window.Add(&content_layer);
344
345   ColoredLayer page_background(SK_ColorWHITE);
346   page_background.SetBounds(gfx::Rect(content_layer.bounds().size()));
347   content_layer.Add(&page_background);
348
349   int frames = atoi(command_line->GetSwitchValueASCII("frames").c_str());
350   scoped_ptr<BenchCompositorObserver> bench;
351
352   if (command_line->HasSwitch("bench-software-scroll")) {
353     bench.reset(new SoftwareScrollBench(&page_background,
354                                         root_window->compositor(),
355                                         frames));
356   } else {
357     bench.reset(new WebGLBench(&page_background,
358                                root_window->compositor(),
359                                frames));
360   }
361
362 #ifndef NDEBUG
363   ui::PrintLayerHierarchy(root_window->layer(), gfx::Point(100, 100));
364 #endif
365
366   root_window->ShowRootWindow();
367   base::MessageLoopForUI::current()->Run();
368   focus_client.reset();
369   root_window.reset();
370
371   return 0;
372 }