Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / ui / aura / bench / bench_main.cc
blob38581f61ece6105a64a04ea36a8bf4930ff910ce
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.
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.h"
11 #include "base/strings/string_split.h"
12 #include "base/time.h"
13 #include "third_party/khronos/GLES2/gl2.h"
14 #include "third_party/skia/include/core/SkXfermode.h"
15 #include "ui/aura/client/default_capture_client.h"
16 #include "ui/aura/env.h"
17 #include "ui/aura/focus_manager.h"
18 #include "ui/aura/root_window.h"
19 #include "ui/aura/test/test_screen.h"
20 #include "ui/aura/window.h"
21 #include "ui/base/hit_test.h"
22 #include "ui/base/resource/resource_bundle.h"
23 #include "ui/base/ui_base_paths.h"
24 #include "ui/compositor/compositor.h"
25 #include "ui/compositor/compositor_observer.h"
26 #include "ui/compositor/debug_utils.h"
27 #include "ui/compositor/layer.h"
28 #include "ui/compositor/test/compositor_test_support.h"
29 #include "ui/gfx/canvas.h"
30 #include "ui/gfx/rect.h"
31 #include "ui/gfx/skia_util.h"
32 #ifndef GL_GLEXT_PROTOTYPES
33 #define GL_GLEXT_PROTOTYPES 1
34 #endif
35 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
36 #include "third_party/khronos/GLES2/gl2ext.h"
38 #if defined(USE_X11)
39 #include "base/message_pump_aurax11.h"
40 #endif
42 using base::TimeTicks;
43 using ui::Compositor;
44 using ui::Layer;
45 using ui::LayerDelegate;
46 using WebKit::WebGraphicsContext3D;
48 namespace {
50 class ColoredLayer : public Layer, public LayerDelegate {
51 public:
52 explicit ColoredLayer(SkColor color)
53 : Layer(ui::LAYER_TEXTURED),
54 color_(color),
55 draw_(true) {
56 set_delegate(this);
59 virtual ~ColoredLayer() {}
61 // Overridden from LayerDelegate:
62 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
63 if (draw_) {
64 canvas->DrawColor(color_);
68 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
71 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
72 return base::Closure();
75 void set_color(SkColor color) { color_ = color; }
76 void set_draw(bool draw) { draw_ = draw; }
78 private:
79 SkColor color_;
80 bool draw_;
82 DISALLOW_COPY_AND_ASSIGN(ColoredLayer);
85 const int kFrames = 100;
87 // Benchmark base class, hooks up drawing callback and displaying FPS.
88 class BenchCompositorObserver : public ui::CompositorObserver {
89 public:
90 explicit BenchCompositorObserver(int max_frames)
91 : start_time_(),
92 frames_(0),
93 max_frames_(max_frames) {
96 virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE {}
98 virtual void OnCompositingStarted(Compositor* compositor,
99 base::TimeTicks start_time) OVERRIDE {}
101 virtual void OnCompositingEnded(Compositor* compositor) OVERRIDE {
102 if (start_time_.is_null()) {
103 start_time_ = TimeTicks::Now();
104 } else {
105 ++frames_;
106 if (frames_ % kFrames == 0) {
107 TimeTicks now = TimeTicks::Now();
108 double ms = (now - start_time_).InMillisecondsF() / kFrames;
109 LOG(INFO) << "FPS: " << 1000.f / ms << " (" << ms << " ms)";
110 start_time_ = now;
113 if (max_frames_ && frames_ == max_frames_) {
114 MessageLoop::current()->Quit();
115 } else {
116 Draw();
120 virtual void OnCompositingAborted(Compositor* compositor) OVERRIDE {}
122 virtual void OnCompositingLockStateChanged(
123 Compositor* compositor) OVERRIDE {}
125 virtual void OnUpdateVSyncParameters(ui::Compositor* compositor,
126 base::TimeTicks timebase,
127 base::TimeDelta interval) OVERRIDE {
130 virtual void Draw() {}
132 int frames() const { return frames_; }
134 private:
135 TimeTicks start_time_;
136 int frames_;
137 int max_frames_;
139 DISALLOW_COPY_AND_ASSIGN(BenchCompositorObserver);
142 class WebGLTexture : public ui::Texture {
143 public:
144 WebGLTexture(WebGraphicsContext3D* context, const gfx::Size& size)
145 : ui::Texture(false, size, 1.0f),
146 context_(context),
147 texture_id_(context_->createTexture()) {
148 context_->bindTexture(GL_TEXTURE_2D, texture_id_);
149 context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
150 context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
151 context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
152 context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
153 context_->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
154 size.width(), size.height(), 0,
155 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
158 virtual unsigned int PrepareTexture() OVERRIDE {
159 return texture_id_;
162 virtual WebGraphicsContext3D* HostContext3D() OVERRIDE {
163 return context_;
166 private:
167 virtual ~WebGLTexture() {
168 context_->deleteTexture(texture_id_);
171 WebGraphicsContext3D* context_;
172 unsigned texture_id_;
174 DISALLOW_COPY_AND_ASSIGN(WebGLTexture);
177 // A benchmark that adds a texture layer that is updated every frame.
178 class WebGLBench : public BenchCompositorObserver {
179 public:
180 WebGLBench(Layer* parent, Compositor* compositor, int max_frames)
181 : BenchCompositorObserver(max_frames),
182 parent_(parent),
183 webgl_(ui::LAYER_TEXTURED),
184 compositor_(compositor),
185 context_(),
186 texture_(),
187 fbo_(0),
188 do_draw_(true) {
189 CommandLine* command_line = CommandLine::ForCurrentProcess();
190 do_draw_ = !command_line->HasSwitch("disable-draw");
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());
203 if (!width || !height) {
204 width = 800;
205 height = 600;
207 gfx::Rect bounds(width, height);
208 webgl_.SetBounds(bounds);
209 parent_->Add(&webgl_);
211 context_.reset(ui::ContextFactory::GetInstance()->CreateOffscreenContext());
212 context_->makeContextCurrent();
213 texture_ = new WebGLTexture(context_.get(), bounds.size());
214 fbo_ = context_->createFramebuffer();
215 compositor->AddObserver(this);
216 webgl_.SetExternalTexture(texture_);
217 context_->bindFramebuffer(GL_FRAMEBUFFER, fbo_);
218 context_->framebufferTexture2D(
219 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
220 GL_TEXTURE_2D, texture_->PrepareTexture(), 0);
221 context_->clearColor(0.f, 1.f, 0.f, 1.f);
222 context_->clear(GL_COLOR_BUFFER_BIT);
223 context_->flush();
226 virtual ~WebGLBench() {
227 context_->makeContextCurrent();
228 context_->deleteFramebuffer(fbo_);
229 webgl_.SetExternalTexture(NULL);
230 texture_ = NULL;
231 compositor_->RemoveObserver(this);
234 virtual void Draw() OVERRIDE {
235 if (do_draw_) {
236 context_->makeContextCurrent();
237 context_->clearColor((frames() % kFrames)*1.0/kFrames, 1.f, 0.f, 1.f);
238 context_->clear(GL_COLOR_BUFFER_BIT);
239 context_->flush();
241 webgl_.SetExternalTexture(texture_);
242 webgl_.SchedulePaint(gfx::Rect(webgl_.bounds().size()));
243 compositor_->ScheduleDraw();
246 private:
247 Layer* parent_;
248 Layer webgl_;
249 Compositor* compositor_;
250 scoped_ptr<WebGraphicsContext3D> context_;
251 scoped_refptr<WebGLTexture> texture_;
253 // The FBO that is used to render to the texture.
254 unsigned int fbo_;
256 // Whether or not to draw to the texture every frame.
257 bool do_draw_;
259 DISALLOW_COPY_AND_ASSIGN(WebGLBench);
262 // A benchmark that paints (in software) all tiles every frame.
263 class SoftwareScrollBench : public BenchCompositorObserver {
264 public:
265 SoftwareScrollBench(ColoredLayer* layer,
266 Compositor* compositor,
267 int max_frames)
268 : BenchCompositorObserver(max_frames),
269 layer_(layer),
270 compositor_(compositor) {
271 compositor->AddObserver(this);
272 layer_->set_draw(
273 !CommandLine::ForCurrentProcess()->HasSwitch("disable-draw"));
276 virtual ~SoftwareScrollBench() {
277 compositor_->RemoveObserver(this);
280 virtual void Draw() OVERRIDE {
281 layer_->set_color(
282 SkColorSetARGBInline(255*(frames() % kFrames)/kFrames, 255, 0, 255));
283 layer_->SchedulePaint(gfx::Rect(layer_->bounds().size()));
286 private:
287 ColoredLayer* layer_;
288 Compositor* compositor_;
290 DISALLOW_COPY_AND_ASSIGN(SoftwareScrollBench);
293 } // namespace
295 int main(int argc, char** argv) {
296 CommandLine::Init(argc, argv);
298 base::AtExitManager exit_manager;
300 ui::RegisterPathProvider();
301 icu_util::Initialize();
302 ResourceBundle::InitSharedInstanceWithLocale("en-US", NULL);
304 MessageLoop message_loop(MessageLoop::TYPE_UI);
305 ui::CompositorTestSupport::Initialize();
306 aura::Env::GetInstance();
307 scoped_ptr<aura::TestScreen> test_screen(
308 aura::TestScreen::CreateFullscreen());
309 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen.get());
310 scoped_ptr<aura::RootWindow> root_window(
311 test_screen->CreateRootWindowForPrimaryDisplay());
312 aura::client::SetCaptureClient(
313 root_window.get(),
314 new aura::client::DefaultCaptureClient(root_window.get()));
316 scoped_ptr<aura::client::FocusClient> focus_client(new aura::FocusManager);
317 aura::client::SetFocusClient(root_window.get(), focus_client.get());
319 // add layers
320 ColoredLayer background(SK_ColorRED);
321 background.SetBounds(root_window->bounds());
322 root_window->layer()->Add(&background);
324 ColoredLayer window(SK_ColorBLUE);
325 window.SetBounds(gfx::Rect(background.bounds().size()));
326 background.Add(&window);
328 Layer content_layer(ui::LAYER_NOT_DRAWN);
330 CommandLine* command_line = CommandLine::ForCurrentProcess();
331 bool force = command_line->HasSwitch("force-render-surface");
332 content_layer.SetForceRenderSurface(force);
333 gfx::Rect bounds(window.bounds().size());
334 bounds.Inset(0, 30, 0, 0);
335 content_layer.SetBounds(bounds);
336 window.Add(&content_layer);
338 ColoredLayer page_background(SK_ColorWHITE);
339 page_background.SetBounds(gfx::Rect(content_layer.bounds().size()));
340 content_layer.Add(&page_background);
342 int frames = atoi(command_line->GetSwitchValueASCII("frames").c_str());
343 scoped_ptr<BenchCompositorObserver> bench;
345 if (command_line->HasSwitch("bench-software-scroll")) {
346 bench.reset(new SoftwareScrollBench(&page_background,
347 root_window->compositor(),
348 frames));
349 } else {
350 bench.reset(new WebGLBench(&page_background,
351 root_window->compositor(),
352 frames));
355 #ifndef NDEBUG
356 ui::PrintLayerHierarchy(root_window->layer(), gfx::Point(100, 100));
357 #endif
359 root_window->ShowRootWindow();
360 MessageLoopForUI::current()->Run();
361 focus_client.reset();
362 root_window.reset();
364 ui::CompositorTestSupport::Terminate();
366 return 0;