1// Copyright 2013 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 "mojo/examples/sample_app/gles2_client_impl.h"
6
7#include <GLES2/gl2.h>
8#include <GLES2/gl2ext.h>
9#include <math.h>
10#include <stdlib.h>
11
12#include "gpu/command_buffer/client/gles2_interface.h"
13#include "mojo/public/c/gles2/gles2.h"
14#include "mojo/public/cpp/environment/environment.h"
15#include "mojo/public/cpp/utility/run_loop.h"
16
17namespace examples {
18namespace {
19
20float CalculateDragDistance(const mojo::Point& start, const mojo::Point& end) {
21  return hypot(static_cast<float>(start.x - end.x),
22               static_cast<float>(start.y - end.y));
23}
24
25float GetRandomColor() {
26  return static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
27}
28
29}
30
31GLES2ClientImpl::GLES2ClientImpl(mojo::CommandBufferPtr command_buffer)
32    : last_time_(mojo::GetTimeTicksNow()), waiting_to_draw_(false) {
33  context_ =
34      MojoGLES2CreateContext(command_buffer.PassMessagePipe().release().value(),
35                             &ContextLostThunk,
36                             this,
37                             mojo::Environment::GetDefaultAsyncWaiter());
38  MojoGLES2MakeCurrent(context_);
39}
40
41GLES2ClientImpl::~GLES2ClientImpl() {
42  MojoGLES2DestroyContext(context_);
43}
44
45void GLES2ClientImpl::SetSize(const mojo::Size& size) {
46  size_ = size;
47  if (size_.width == 0 || size_.height == 0)
48    return;
49  static_cast<gpu::gles2::GLES2Interface*>(
50      MojoGLES2GetGLES2Interface(context_))->ResizeCHROMIUM(size_.width,
51                                                            size_.height,
52                                                            1);
53  cube_.Init(size_.width, size_.height);
54  WantToDraw();
55}
56
57void GLES2ClientImpl::HandleInputEvent(const mojo::Event& event) {
58  switch (event.action) {
59  case mojo::EVENT_TYPE_MOUSE_PRESSED:
60  case mojo::EVENT_TYPE_TOUCH_PRESSED:
61    if (event.flags & mojo::EVENT_FLAGS_RIGHT_MOUSE_BUTTON)
62      break;
63    capture_point_ = *event.location_data->in_view_location;
64    last_drag_point_ = capture_point_;
65    drag_start_time_ = mojo::GetTimeTicksNow();
66    break;
67  case mojo::EVENT_TYPE_MOUSE_DRAGGED:
68  case mojo::EVENT_TYPE_TOUCH_MOVED: {
69    if (event.flags & mojo::EVENT_FLAGS_RIGHT_MOUSE_BUTTON)
70      break;
71    int direction =
72        (event.location_data->in_view_location->y < last_drag_point_.y ||
73         event.location_data->in_view_location->x > last_drag_point_.x)
74        ? 1 : -1;
75    cube_.set_direction(direction);
76    cube_.UpdateForDragDistance(CalculateDragDistance(
77        last_drag_point_, *event.location_data->in_view_location));
78    WantToDraw();
79
80    last_drag_point_ = *event.location_data->in_view_location;
81    break;
82  }
83  case mojo::EVENT_TYPE_MOUSE_RELEASED:
84  case mojo::EVENT_TYPE_TOUCH_RELEASED: {
85    if (event.flags & mojo::EVENT_FLAGS_RIGHT_MOUSE_BUTTON) {
86      cube_.set_color(GetRandomColor(), GetRandomColor(), GetRandomColor());
87      break;
88    }
89    MojoTimeTicks offset = mojo::GetTimeTicksNow() - drag_start_time_;
90    float delta = static_cast<float>(offset) / 1000000.;
91    cube_.SetFlingMultiplier(CalculateDragDistance(
92        capture_point_, *event.location_data->in_view_location), delta);
93
94    capture_point_ = last_drag_point_ = mojo::Point();
95    WantToDraw();
96    break;
97  }
98  default:
99    break;
100  }
101}
102
103void GLES2ClientImpl::ContextLost() {
104}
105
106void GLES2ClientImpl::ContextLostThunk(void* closure) {
107  static_cast<GLES2ClientImpl*>(closure)->ContextLost();
108}
109
110struct DrawRunnable {
111  explicit DrawRunnable(GLES2ClientImpl* impl) : impl(impl) {}
112  virtual ~DrawRunnable() {}
113
114  void Run() const { impl->Draw(); }
115
116  GLES2ClientImpl* impl;
117};
118
119void GLES2ClientImpl::WantToDraw() {
120  if (waiting_to_draw_)
121    return;
122  waiting_to_draw_ = true;
123  mojo::RunLoop::current()->PostDelayedTask(mojo::Closure(DrawRunnable(this)),
124                                            MojoTimeTicks(16667));
125}
126
127void GLES2ClientImpl::Draw() {
128  waiting_to_draw_ = false;
129  MojoTimeTicks now = mojo::GetTimeTicksNow();
130  MojoTimeTicks offset = now - last_time_;
131  float delta = static_cast<float>(offset) / 1000000.;
132  last_time_ = now;
133  cube_.UpdateForTimeDelta(delta);
134  cube_.Draw();
135
136  MojoGLES2SwapBuffers();
137  WantToDraw();
138}
139
140}  // namespace examples
141