Chromium Code Reviews| Index: ui/aura/bench/bench_main.cc |
| diff --git a/ui/aura/bench/bench_main.cc b/ui/aura/bench/bench_main.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d47f669b199dd50273d2cabd85efb97f93b8a0d8 |
| --- /dev/null |
| +++ b/ui/aura/bench/bench_main.cc |
| @@ -0,0 +1,321 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "base/at_exit.h" |
| +#include "base/bind.h" |
| +#include "base/command_line.h" |
| +#include "base/i18n/icu_util.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/message_loop.h" |
| +#include "base/string_split.h" |
| +#include "base/time.h" |
| +#include "third_party/skia/include/core/SkXfermode.h" |
| +#include "ui/aura/env.h" |
| +#include "ui/aura/event.h" |
| +#include "ui/aura/root_window.h" |
| +#include "ui/aura/single_monitor_manager.h" |
| +#include "ui/aura/window.h" |
| +#include "ui/base/hit_test.h" |
| +#include "ui/base/resource/resource_bundle.h" |
| +#include "ui/base/ui_base_paths.h" |
| +#include "ui/compositor/compositor.h" |
| +#include "ui/compositor/compositor_observer.h" |
| +#include "ui/compositor/debug_utils.h" |
| +#include "ui/compositor/layer.h" |
| +#include "ui/compositor/test/compositor_test_support.h" |
| +#include "ui/gfx/canvas.h" |
| +#include "ui/gfx/rect.h" |
| +#include "ui/gfx/skia_util.h" |
| +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h" |
|
sky
2012/05/25 15:30:42
nit: sort
piman
2012/05/25 22:11:28
Done.
|
| +#include "third_party/khronos/GLES2/gl2.h" |
| +#ifndef GL_GLEXT_PROTOTYPES |
| +#define GL_GLEXT_PROTOTYPES 1 |
| +#endif |
| +#include "third_party/khronos/GLES2/gl2ext.h" |
| + |
| +#if defined(USE_X11) |
| +#include "base/message_pump_x.h" |
| +#endif |
| + |
| +using base::TimeTicks; |
| +using ui::Compositor; |
| +using ui::Layer; |
| +using ui::LayerDelegate; |
| +using WebKit::WebGraphicsContext3D; |
| + |
| +namespace { |
| + |
| +class ColoredLayer : public Layer, public LayerDelegate { |
| + public: |
| + explicit ColoredLayer(SkColor color) |
| + : Layer(ui::LAYER_TEXTURED), |
| + color_(color), |
| + draw_(true) { |
| + set_delegate(this); |
| + } |
| + |
| + virtual ~ColoredLayer() { } |
|
sky
2012/05/25 15:30:42
nit: { } -> {}
piman
2012/05/25 22:11:28
Done.
|
| + |
| + // Overridden from LayerDelegate: |
| + virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE { |
| + if (draw_) { |
| + canvas->DrawColor(color_); |
| + } |
| + } |
| + |
| + virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE { |
| + } |
| + |
| + void set_color(SkColor color) { color_ = color; } |
| + void set_draw(bool draw) { draw_ = draw; } |
| + |
| + private: |
| + SkColor color_; |
| + bool draw_; |
| +}; |
|
sky
2012/05/25 15:30:42
DISALLOW_... (here and all classes you're creating
piman
2012/05/25 22:11:28
Done.
|
| + |
| +const int kFrames = 100; |
| + |
| +// Benchmark base class, hooks up drawing callback and displaying FPS. |
| +class BenchCompositorObserver : public ui::CompositorObserver { |
| + public: |
| + explicit BenchCompositorObserver(int max_frames) |
| + : start_time_(), |
| + frames_(0), |
| + max_frames_(max_frames) { |
| + } |
| + virtual void OnCompositingStarted(Compositor* compositor) {} |
|
sky
2012/05/25 15:30:42
OVERRIDE (here and 90)
piman
2012/05/25 22:11:28
Done.
|
| + |
| + virtual void OnCompositingEnded(Compositor* compositor) { |
| + if (start_time_.is_null()) { |
| + start_time_ = TimeTicks::Now(); |
| + } else { |
| + ++frames_; |
| + if (frames_ % kFrames == 0) { |
| + TimeTicks now = TimeTicks::Now(); |
| + double ms = (now - start_time_).InMillisecondsF() / kFrames; |
| + LOG(INFO) << "FPS: " << 1000.f / ms << " (" << ms << " ms)"; |
| + start_time_ = now; |
| + } |
| + } |
| + if (max_frames_ && frames_ == max_frames_) { |
| + MessageLoop::current()->Quit(); |
| + } else { |
| + MessageLoop::current()->PostTask( |
|
sky
2012/05/25 15:30:42
Why do you need this? And how to you guarantee thi
piman
2012/05/25 22:11:28
There was a bug that prevented ScheduleDraw from w
|
| + FROM_HERE, |
| + base::Bind(&BenchCompositorObserver::Draw, base::Unretained(this))); |
| + } |
| + } |
| + |
| + virtual void Draw() {} |
| + |
| + int frames() const { return frames_; } |
| + |
| + private: |
| + TimeTicks start_time_; |
| + int frames_; |
| + int max_frames_; |
| +}; |
| + |
| +class WebGLTexture : public ui::Texture { |
| + public: |
| + WebGLTexture(WebGraphicsContext3D* context, const gfx::Size& size) |
| + : ui::Texture(false, size), |
| + context_(context) { |
| + set_texture_id(context_->createTexture()); |
| + context_->bindTexture(GL_TEXTURE_2D, texture_id()); |
| + context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| + context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| + context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| + context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| + context_->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, |
| + size.width(), size.height(), 0, |
| + GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
| + } |
| + |
| + virtual ~WebGLTexture() { |
| + context_->deleteTexture(texture_id()); |
| + } |
| + |
| + private: |
| + WebGraphicsContext3D* context_; |
| +}; |
| + |
| +// A benchmark that adds a texture layer that is updated every frame. |
| +class WebGLBench : public BenchCompositorObserver { |
| + public: |
| + WebGLBench(Layer* parent, Compositor* compositor, int max_frames) |
| + : BenchCompositorObserver(max_frames), |
| + parent_(parent), |
| + webgl_(ui::LAYER_TEXTURED), |
| + compositor_(compositor), |
| + context_(), |
| + texture_(), |
| + fbo_(0), |
| + do_draw_(true) { |
| + CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| + do_draw_ = !command_line->HasSwitch("disable-draw"); |
| + |
| + std::string webgl_size = command_line->GetSwitchValueASCII("webgl-size"); |
| + int width = 0; |
| + int height = 0; |
| + if (!webgl_size.empty()) { |
| + std::vector<std::string> split_size; |
| + base::SplitString(webgl_size, 'x', &split_size); |
| + if (split_size.size() == 2) { |
| + width = atoi(split_size[0].c_str()); |
| + height = atoi(split_size[1].c_str()); |
| + } |
| + } |
| + if (!width || !height) { |
| + width = 800; |
| + height = 600; |
| + } |
| + gfx::Rect bounds(width, height); |
| + webgl_.SetBounds(bounds); |
| + parent_->Add(&webgl_); |
| + |
| + context_.reset( |
| + ui::ContextFactory::GetInstance()->CreateOffscreenContext(compositor)); |
| + context_->makeContextCurrent(); |
| + texture_ = new WebGLTexture(context_.get(), bounds.size()); |
| + fbo_ = context_->createFramebuffer(); |
| + compositor->AddObserver(this); |
| + webgl_.SetExternalTexture(texture_); |
| + context_->bindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| + context_->framebufferTexture2D( |
| + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
| + GL_TEXTURE_2D, texture_->texture_id(), 0); |
| + context_->clearColor(0.f, 1.f, 0.f, 1.f); |
| + context_->clear(GL_COLOR_BUFFER_BIT); |
| + context_->flush(); |
| + } |
| + |
| + virtual ~WebGLBench() { |
| + context_->makeContextCurrent(); |
| + context_->deleteFramebuffer(fbo_); |
| + webgl_.SetExternalTexture(NULL); |
| + texture_ = NULL; |
| + compositor_->RemoveObserver(this); |
| + } |
| + |
| + virtual void Draw() { |
|
sky
2012/05/25 15:30:42
OVERRIDE
piman
2012/05/25 22:11:28
Done.
|
| + if (do_draw_) { |
| + context_->makeContextCurrent(); |
| + context_->clearColor((frames() % kFrames)*1.0/kFrames, 1.f, 0.f, 1.f); |
| + context_->clear(GL_COLOR_BUFFER_BIT); |
| + context_->flush(); |
| + } |
| + webgl_.SetExternalTexture(texture_); |
| + webgl_.SchedulePaint(gfx::Rect(webgl_.bounds().size())); |
| + compositor_->ScheduleDraw(); |
| + } |
| + |
| + private: |
| + Layer* parent_; |
| + Layer webgl_; |
| + Compositor* compositor_; |
| + scoped_ptr<WebGraphicsContext3D> context_; |
| + scoped_refptr<WebGLTexture> texture_; |
| + unsigned int fbo_; |
|
sky
2012/05/25 15:30:42
How about a description of fbo_ and do_draw_ ?
piman
2012/05/25 22:11:28
Done.
|
| + bool do_draw_; |
| +}; |
| + |
| +// A benchmark that paints (in software) all tiles every frame. |
| +class SoftwareScrollBench : public BenchCompositorObserver { |
| + public: |
| + SoftwareScrollBench(ColoredLayer* layer, |
| + Compositor* compositor, |
| + int max_frames) |
| + : BenchCompositorObserver(max_frames), |
| + layer_(layer), |
| + compositor_(compositor) { |
| + compositor->AddObserver(this); |
| + layer_->set_draw( |
| + !CommandLine::ForCurrentProcess()->HasSwitch("disable-draw")); |
| + } |
| + |
| + virtual ~SoftwareScrollBench() { |
| + compositor_->RemoveObserver(this); |
| + } |
| + |
| + virtual void Draw() { |
| + layer_->set_color( |
| + SkColorSetARGBInline(255*(frames() % kFrames)/kFrames, 255, 0, 255)); |
| + layer_->SchedulePaint(gfx::Rect(layer_->bounds().size())); |
| + } |
| + |
| + private: |
| + ColoredLayer* layer_; |
| + Compositor* compositor_; |
| +}; |
| + |
| +} // anonymous namespace |
| + |
| +int main(int argc, char** argv) { |
| + CommandLine::Init(argc, argv); |
| + |
| + base::AtExitManager exit_manager; |
| + |
| + ui::RegisterPathProvider(); |
| + icu_util::Initialize(); |
| + ResourceBundle::InitSharedInstanceWithLocale("en-US", NULL); |
| + |
| + MessageLoop message_loop(MessageLoop::TYPE_UI); |
| + ui::CompositorTestSupport::Initialize(); |
| + aura::SingleMonitorManager* manager = new aura::SingleMonitorManager; |
| + manager->set_use_fullscreen_host_window(true); |
| + aura::Env::GetInstance()->SetMonitorManager(manager); |
| + scoped_ptr<aura::RootWindow> root_window( |
| + aura::MonitorManager::CreateRootWindowForPrimaryMonitor()); |
| + |
| + |
| + // add layers |
| + ColoredLayer background(SK_ColorRED); |
| + background.SetBounds(root_window->bounds()); |
| + root_window->layer()->Add(&background); |
| + |
| + ColoredLayer window(SK_ColorBLUE); |
| + window.SetBounds(gfx::Rect(background.bounds().size())); |
| + background.Add(&window); |
| + |
| + Layer content_layer(ui::LAYER_NOT_DRAWN); |
| + |
| + CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| + bool force = command_line->HasSwitch("force-render-surface"); |
| + content_layer.SetForceRenderSurface(force); |
| + gfx::Rect bounds(window.bounds().size()); |
| + bounds.Inset(0, 30, 0, 0); |
| + content_layer.SetBounds(bounds); |
| + window.Add(&content_layer); |
| + |
| + ColoredLayer page_background(SK_ColorWHITE); |
| + page_background.SetBounds(gfx::Rect(content_layer.bounds().size())); |
| + content_layer.Add(&page_background); |
| + |
| + int frames = atoi(command_line->GetSwitchValueASCII("frames").c_str()); |
| + scoped_ptr<BenchCompositorObserver> bench; |
| + |
| + if (command_line->HasSwitch("bench-software-scroll")) { |
| + bench.reset(new SoftwareScrollBench(&page_background, |
| + root_window->compositor(), |
| + frames)); |
| + } else { |
| + bench.reset(new WebGLBench(&page_background, |
| + root_window->compositor(), |
| + frames)); |
| + } |
| + |
| +#ifndef NDEBUG |
| + ui::PrintLayerHierarchy(root_window->layer(), gfx::Point(100, 100)); |
| +#endif |
| + |
| + root_window->ShowRootWindow(); |
| + MessageLoopForUI::current()->Run(); |
| + root_window.reset(); |
| + |
| + ui::CompositorTestSupport::Terminate(); |
| + |
| + return 0; |
| +} |