15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(USE_X11)
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <X11/Xlib.h>
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/at_exit.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/icu_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_loop.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "cc/output/context_provider.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gpu/command_buffer/client/gles2_interface.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/khronos/GLES2/gl2.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkXfermode.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/default_capture_client.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/env.h"
238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "ui/aura/test/test_focus_client.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/test/test_screen.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h"
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_tree_host.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/hit_test.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/compositor.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/compositor_observer.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/debug_utils.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer.h"
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/compositor/test/in_process_context_factory.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/skia_util.h"
36a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ui/gfx/x/x11_connection.h"
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gl/gl_surface.h"
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef GL_GLEXT_PROTOTYPES
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GL_GLEXT_PROTOTYPES 1
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/khronos/GLES2/gl2ext.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ui::Compositor;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ui::Layer;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ui::LayerDelegate;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ColoredLayer : public Layer, public LayerDelegate {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ColoredLayer(SkColor color)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : Layer(ui::LAYER_TEXTURED),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        color_(color),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        draw_(true) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_delegate(this);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ColoredLayer() {}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden from LayerDelegate:
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (draw_) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      canvas->DrawColor(color_);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnDelegatedFrameDamage(
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const gfx::Rect& damage_rect_in_dip) OVERRIDE {}
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::Closure();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_color(SkColor color) { color_ = color; }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_draw(bool draw) { draw_ = draw; }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkColor color_;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool draw_;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ColoredLayer);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kFrames = 100;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Benchmark base class, hooks up drawing callback and displaying FPS.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BenchCompositorObserver : public ui::CompositorObserver {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit BenchCompositorObserver(int max_frames)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : start_time_(),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        frames_(0),
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        max_frames_(max_frames) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE {}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnCompositingStarted(Compositor* compositor,
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    base::TimeTicks start_time) OVERRIDE {}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnCompositingEnded(Compositor* compositor) OVERRIDE {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (start_time_.is_null()) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_time_ = TimeTicks::Now();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++frames_;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (frames_ % kFrames == 0) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TimeTicks now = TimeTicks::Now();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        double ms = (now - start_time_).InMillisecondsF() / kFrames;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(INFO) << "FPS: " << 1000.f / ms << " (" << ms << " ms)";
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        start_time_ = now;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (max_frames_ && frames_ == max_frames_) {
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::MessageLoop::current()->Quit();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Draw();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnCompositingAborted(Compositor* compositor) OVERRIDE {}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnCompositingLockStateChanged(
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Compositor* compositor) OVERRIDE {}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Draw() {}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int frames() const { return frames_; }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeTicks start_time_;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int frames_;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int max_frames_;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BenchCompositorObserver);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ReturnMailbox(scoped_refptr<cc::ContextProvider> context_provider,
142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   GLuint texture,
143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   GLuint sync_point,
144c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   bool is_lost) {
145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gl->WaitSyncPointCHROMIUM(sync_point);
147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gl->DeleteTextures(1, &texture);
148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gl->ShallowFlushCHROMIUM();
149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A benchmark that adds a texture layer that is updated every frame.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WebGLBench : public BenchCompositorObserver {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WebGLBench(ui::ContextFactory* context_factory,
15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)             Layer* parent,
15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)             Compositor* compositor,
15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)             int max_frames)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : BenchCompositorObserver(max_frames),
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        parent_(parent),
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        webgl_(ui::LAYER_TEXTURED),
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        compositor_(compositor),
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fbo_(0),
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        do_draw_(true) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine* command_line = CommandLine::ForCurrentProcess();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do_draw_ = !command_line->HasSwitch("disable-draw");
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string webgl_size = command_line->GetSwitchValueASCII("webgl-size");
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int width = 0;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int height = 0;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!webgl_size.empty()) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<std::string> split_size;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::SplitString(webgl_size, 'x', &split_size);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (split_size.size() == 2) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        width = atoi(split_size[0].c_str());
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        height = atoi(split_size[1].c_str());
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!width || !height) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      width = 800;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      height = 600;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect bounds(width, height);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    webgl_.SetBounds(bounds);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parent_->Add(&webgl_);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    context_provider_ = context_factory->SharedMainThreadContextProvider();
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    GLuint texture = 0;
189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gl->GenTextures(1, &texture);
190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gl->BindTexture(GL_TEXTURE_2D, texture);
191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
193c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gl->TexImage2D(GL_TEXTURE_2D,
196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   0,
197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   GL_RGBA,
198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   width,
199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   height,
200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   0,
201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   GL_RGBA,
202c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   GL_UNSIGNED_BYTE,
203c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   NULL);
204c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gpu::Mailbox mailbox;
205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gl->GenMailboxCHROMIUM(mailbox.name);
206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gl->GenFramebuffers(1, &fbo_);
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gl->FramebufferTexture2D(
211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gl->ClearColor(0.f, 1.f, 0.f, 1.f);
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gl->Clear(GL_COLOR_BUFFER_BIT);
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gl->Flush();
215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    GLuint sync_point = gl->InsertSyncPointCHROMIUM();
217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    webgl_.SetTextureMailbox(
218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        cc::TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        cc::SingleReleaseCallback::Create(
220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            base::Bind(ReturnMailbox, context_provider_, texture)),
221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        bounds.size());
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    compositor->AddObserver(this);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~WebGLBench() {
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    webgl_.SetShowPaintedContent();
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gl->DeleteFramebuffers(1, &fbo_);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    compositor_->RemoveObserver(this);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Draw() OVERRIDE {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (do_draw_) {
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gl->ClearColor((frames() % kFrames)*1.0/kFrames, 1.f, 0.f, 1.f);
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gl->Clear(GL_COLOR_BUFFER_BIT);
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gl->Flush();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    webgl_.SchedulePaint(gfx::Rect(webgl_.bounds().size()));
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    compositor_->ScheduleDraw();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Layer* parent_;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Layer webgl_;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Compositor* compositor_;
2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<cc::ContextProvider> context_provider_;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The FBO that is used to render to the texture.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int fbo_;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether or not to draw to the texture every frame.
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool do_draw_;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WebGLBench);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A benchmark that paints (in software) all tiles every frame.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SoftwareScrollBench : public BenchCompositorObserver {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SoftwareScrollBench(ColoredLayer* layer,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      Compositor* compositor,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int max_frames)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : BenchCompositorObserver(max_frames),
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        layer_(layer),
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        compositor_(compositor) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    compositor->AddObserver(this);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    layer_->set_draw(
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !CommandLine::ForCurrentProcess()->HasSwitch("disable-draw"));
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SoftwareScrollBench() {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    compositor_->RemoveObserver(this);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Draw() OVERRIDE {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    layer_->set_color(
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkColorSetARGBInline(255*(frames() % kFrames)/kFrames, 255, 0, 255));
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    layer_->SchedulePaint(gfx::Rect(layer_->bounds().size()));
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ColoredLayer* layer_;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Compositor* compositor_;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SoftwareScrollBench);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char** argv) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine::Init(argc, argv);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AtExitManager exit_manager;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(USE_X11)
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // This demo uses InProcessContextFactory which uses X on a separate Gpu
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // thread.
299a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::InitializeThreadedX11();
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::GLSurface::InitializeOneOff();
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The ContextFactory must exist before any Compositors are created.
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<ui::InProcessContextFactory> context_factory(
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new ui::InProcessContextFactory());
30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::i18n::InitializeICU();
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::MessageLoopForUI message_loop;
311010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  aura::Env::CreateInstance(true);
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  aura::Env::GetInstance()->set_context_factory(context_factory.get());
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::TestScreen> test_screen(
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      aura::TestScreen::CreateFullscreen());
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen.get());
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<aura::WindowTreeHost> host(
317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      test_screen->CreateHostForPrimaryDisplay());
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::client::SetCaptureClient(
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      host->window(),
320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new aura::client::DefaultCaptureClient(host->window()));
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  scoped_ptr<aura::client::FocusClient> focus_client(
3238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      new aura::test::TestFocusClient);
324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  aura::client::SetFocusClient(host->window(), focus_client.get());
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // add layers
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ColoredLayer background(SK_ColorRED);
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  background.SetBounds(host->window()->bounds());
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  host->window()->layer()->Add(&background);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ColoredLayer window(SK_ColorBLUE);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window.SetBounds(gfx::Rect(background.bounds().size()));
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background.Add(&window);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Layer content_layer(ui::LAYER_NOT_DRAWN);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine* command_line = CommandLine::ForCurrentProcess();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool force = command_line->HasSwitch("force-render-surface");
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_layer.SetForceRenderSurface(force);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect bounds(window.bounds().size());
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds.Inset(0, 30, 0, 0);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_layer.SetBounds(bounds);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window.Add(&content_layer);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ColoredLayer page_background(SK_ColorWHITE);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  page_background.SetBounds(gfx::Rect(content_layer.bounds().size()));
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_layer.Add(&page_background);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int frames = atoi(command_line->GetSwitchValueASCII("frames").c_str());
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BenchCompositorObserver> bench;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command_line->HasSwitch("bench-software-scroll")) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bench.reset(new SoftwareScrollBench(&page_background,
354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                        host->compositor(),
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        frames));
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bench.reset(new WebGLBench(context_factory.get(),
35846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                               &page_background,
359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               host->compositor(),
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               frames));
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
364a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ui::PrintLayerHierarchy(host->window()->layer(), gfx::Point(100, 100));
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  host->Show();
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoopForUI::current()->Run();
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  focus_client.reset();
370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  host.reset();
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
374