Add helpers for creating UI components.

These helpers make it easier to use Mozart in C++ and greatly
reduce the amount of boilerplate involved in writing simple
applications.

View implementations:

- BaseView: A base implementation of the View interface.
- GLView: A View with an associated GLRenderer which takes care
  of allocating, binding, and recycling textures.
- GaneshView: A View with an associated GaneshRenderer which takes
  care of setting up a GaneshContext and drawing to canvas.

View providers:

- ViewProviderApp: Skeleton of a simple app which offers the
  ViewProvider interface and vends Views on demand.
- ContextViewerApp: Skeleton of a simple app which offers the
  ContentHandler interface and vends ViewProviders on demand.

Helpers:

- Choreographer: Coordinates the scheduling of drawing operations
  on behalf of a View and compensates for lag.
- InputHandler: Binds an InputListener on behalf of a View.

BUG=
R=abarth@google.com, viettrungluu@chromium.org

Review URL: https://codereview.chromium.org/1556803002 .
diff --git a/mojo/ui/gl_renderer.cc b/mojo/ui/gl_renderer.cc
new file mode 100644
index 0000000..3adf507
--- /dev/null
+++ b/mojo/ui/gl_renderer.cc
@@ -0,0 +1,161 @@
+// Copyright 2015 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 "mojo/ui/gl_renderer.h"
+
+#ifndef GL_GLEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES
+#endif
+#include <GLES2/gl2.h>
+#include <GLES2/gl2extmojo.h>
+
+#include "mojo/gpu/gl_context.h"
+#include "mojo/gpu/gl_texture.h"
+
+namespace mojo {
+namespace ui {
+
+GLRenderer::GLRenderer(base::WeakPtr<mojo::GLContext> gl_context,
+                       uint32_t max_recycled_textures)
+    : gl_context_(gl_context),
+      max_recycled_textures_(max_recycled_textures),
+      weak_factory_(this) {}
+
+GLRenderer::~GLRenderer() {}
+
+std::unique_ptr<mojo::GLTexture> GLRenderer::GetTexture(
+    const mojo::Size& requested_size) {
+  if (!gl_context_) {
+    recycled_textures_.clear();
+    return nullptr;
+  }
+
+  while (!recycled_textures_.empty()) {
+    GLRecycledTextureInfo texture_info(std::move(recycled_textures_.front()));
+    recycled_textures_.pop_front();
+    if (texture_info.first->size().Equals(requested_size)) {
+      gl_context_->MakeCurrent();
+      glWaitSyncPointCHROMIUM(texture_info.second);
+      return std::move(texture_info.first);
+    }
+  }
+
+  return std::unique_ptr<GLTexture>(new GLTexture(gl_context_, requested_size));
+}
+
+mojo::gfx::composition::ResourcePtr GLRenderer::BindTextureResource(
+    std::unique_ptr<GLTexture> texture) {
+  if (!gl_context_)
+    return nullptr;
+
+  // Produce the texture.
+  gl_context_->MakeCurrent();
+  glBindTexture(GL_TEXTURE_2D, texture->texture_id());
+  GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
+  glGenMailboxCHROMIUM(mailbox);
+  glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox);
+  glBindTexture(GL_TEXTURE_2D, 0);
+  GLuint sync_point = glInsertSyncPointCHROMIUM();
+
+  // Populate the resource description.
+  auto resource = mojo::gfx::composition::Resource::New();
+  resource->set_mailbox_texture(
+      mojo::gfx::composition::MailboxTextureResource::New());
+  resource->get_mailbox_texture()->mailbox_name.resize(sizeof(mailbox));
+  memcpy(resource->get_mailbox_texture()->mailbox_name.data(), mailbox,
+         sizeof(mailbox));
+  resource->get_mailbox_texture()->sync_point = sync_point;
+  resource->get_mailbox_texture()->size = texture->size().Clone();
+  resource->get_mailbox_texture()->callback =
+      (new GLTextureReleaser(
+           weak_factory_.GetWeakPtr(),
+           GLRecycledTextureInfo(std::move(texture), sync_point)))
+          ->StrongBind()
+          .Pass();
+
+  bound_textures_++;
+  DVLOG(2) << "bind: bound_textures=" << bound_textures_;
+  return resource;
+}
+
+mojo::gfx::composition::ResourcePtr GLRenderer::DrawGL(
+    const mojo::Size& size,
+    bool with_depth,
+    const DrawGLCallback& callback) {
+  std::unique_ptr<mojo::GLTexture> texture = GetTexture(size);
+  DCHECK(texture);
+
+  GLuint fbo = 0u;
+  glGenFramebuffers(1, &fbo);
+  glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                         texture->texture_id(), 0);
+
+  GLuint depth_buffer = 0u;
+  if (with_depth) {
+    glGenRenderbuffers(1, &depth_buffer);
+    glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size.width,
+                          size.height);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                              GL_RENDERBUFFER, depth_buffer);
+  }
+
+  DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+            glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+  glViewport(0, 0, size.width, size.height);
+  callback.Run();
+
+  if (with_depth)
+    glDeleteRenderbuffers(1, &depth_buffer);
+  glDeleteFramebuffers(1, &fbo);
+
+  return BindTextureResource(std::move(texture));
+}
+
+void GLRenderer::ReleaseTexture(GLRecycledTextureInfo texture_info,
+                                bool recyclable) {
+  DCHECK(bound_textures_);
+  bound_textures_--;
+  if (recyclable && recycled_textures_.size() < max_recycled_textures_) {
+    recycled_textures_.emplace_back(std::move(texture_info));
+  }
+  DVLOG(2) << "release: bound_textures=" << bound_textures_
+           << ", recycled_textures=" << recycled_textures_.size();
+}
+
+GLRenderer::GLTextureReleaser::GLTextureReleaser(
+    const base::WeakPtr<GLRenderer>& provider,
+    GLRecycledTextureInfo info)
+    : provider_(provider), texture_info_(std::move(info)), binding_(this) {}
+
+GLRenderer::GLTextureReleaser::~GLTextureReleaser() {
+  // It's possible for the object to be destroyed due to a connection
+  // error on the callback pipe.  When this happens we don't want to
+  // recycle the texture since we have too little knowledge about its
+  // state to confirm that it will be safe to do so.
+  Release(false /*recyclable*/);
+}
+
+mojo::gfx::composition::MailboxTextureCallbackPtr
+GLRenderer::GLTextureReleaser::StrongBind() {
+  mojo::gfx::composition::MailboxTextureCallbackPtr callback;
+  binding_.Bind(mojo::GetProxy(&callback));
+  return callback;
+}
+
+void GLRenderer::GLTextureReleaser::OnMailboxTextureReleased() {
+  Release(true /*recyclable*/);
+}
+
+void GLRenderer::GLTextureReleaser::Release(bool recyclable) {
+  if (provider_) {
+    provider_->ReleaseTexture(std::move(texture_info_), recyclable);
+    provider_.reset();
+  }
+}
+
+}  // namespace ui
+}  // namespace mojo