OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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 <EGL/egl.h> |
| 6 #include <GL/gl.h> |
| 7 #include <glib.h> |
| 8 #include <stdlib.h> |
| 9 #include <stdio.h> |
| 10 #include <X11/keysym.h> |
| 11 #include <wayland-client.h> |
| 12 #include <wayland-egl.h> |
| 13 |
| 14 #include "base/at_exit.h" |
| 15 #include "base/command_line.h" |
| 16 #include "base/logging.h" |
| 17 #include "base/memory/ref_counted.h" |
| 18 #include "base/message_loop.h" |
| 19 #include "base/message_pump_wayland.h" |
| 20 #include "base/wayland/wayland_event.h" |
| 21 #include "ui/gfx/rect.h" |
| 22 #include "ui/gl/gl_bindings.h" |
| 23 #include "ui/gl/gl_context.h" |
| 24 #include "ui/gl/gl_implementation.h" |
| 25 #include "ui/gl/gl_surface_egl.h" |
| 26 #include "ui/wayland/demos/util.h" |
| 27 #include "ui/wayland/wayland_display.h" |
| 28 #include "ui/wayland/wayland_widget.h" |
| 29 #include "ui/wayland/wayland_window.h" |
| 30 |
| 31 namespace { |
| 32 |
| 33 GMainLoop* g_loop = g_main_loop_new(NULL, FALSE); |
| 34 |
| 35 // This is a sample Wayland widget intended to exercise some basic |
| 36 // functionality. It also serves as an example of how to use the |
| 37 // Wayland wrappers. |
| 38 class Widget : public ui::WaylandWidget { |
| 39 public: |
| 40 explicit Widget(ui::WaylandDisplay* display); |
| 41 virtual ~Widget(); |
| 42 |
| 43 private: |
| 44 // Overwritten from WaylandWidget. |
| 45 void OnMotionNotify(base::wayland::WaylandEvent event); |
| 46 void OnButtonNotify(base::wayland::WaylandEvent event); |
| 47 void OnKeyNotify(base::wayland::WaylandEvent event); |
| 48 void OnPointerFocus(base::wayland::WaylandEvent event); |
| 49 void OnKeyboardFocus(base::wayland::WaylandEvent event); |
| 50 |
| 51 void OnGeometryChange(base::wayland::WaylandEvent event); |
| 52 |
| 53 // This function is used to schedule a redraw. The |data| parameter is |
| 54 // actually the WaylandWidget that needs to redraw. |
| 55 static gboolean IdleRedraw(void* data); |
| 56 |
| 57 // This is the actual redraw function. This will be called from the |
| 58 // IdleRedraw function. |
| 59 void Redraw(); |
| 60 |
| 61 // Pointer to the WaylandDisplay. We don't own it, but we do need it to |
| 62 // perform some initialization. |
| 63 ui::WaylandDisplay* display_; |
| 64 |
| 65 // The Wayland window associated with the widget. The window is where the |
| 66 // actual surface is stored. |
| 67 ui::WaylandWindow window_; |
| 68 |
| 69 // The current allocation of the window. |
| 70 gfx::Rect allocation_; |
| 71 |
| 72 scoped_refptr<gfx::GLSurface> surface_; |
| 73 scoped_refptr<gfx::GLContext> context_; |
| 74 |
| 75 GLuint program_; |
| 76 }; |
| 77 |
| 78 Widget::Widget(ui::WaylandDisplay* display) |
| 79 : display_(display), |
| 80 window_(NULL, display), |
| 81 allocation_(0, 0, 400, 400), |
| 82 program_(0) { |
| 83 |
| 84 window_.Flush(); |
| 85 |
| 86 // First we need to create the accelerated surface. |
| 87 window_.set_egl_window(wl_egl_window_create(window_.surface(), |
| 88 allocation_.width(), |
| 89 allocation_.height())); |
| 90 |
| 91 // Create the EGL window surface and the GL context. |
| 92 surface_ = gfx::GLSurface::CreateViewGLSurface(false, &window_); |
| 93 context_ = gfx::GLContext::CreateGLContext(NULL, surface_.get(), |
| 94 gfx::PreferDiscreteGpu); |
| 95 |
| 96 if (!context_->MakeCurrent(surface_.get())) |
| 97 DLOG(ERROR) << "Failed to make surface current"; |
| 98 |
| 99 GLuint vert_shader = util::CompileShader(GL_VERTEX_SHADER, |
| 100 "attribute vec4 vPosition;" |
| 101 "void main() {" |
| 102 " gl_Position = vPosition;" |
| 103 "}"); |
| 104 |
| 105 GLuint frag_shader = util::CompileShader(GL_FRAGMENT_SHADER, |
| 106 "void main() {" |
| 107 " gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);" |
| 108 "}"); |
| 109 |
| 110 program_ = glCreateProgram(); |
| 111 glAttachShader(program_, vert_shader); |
| 112 glAttachShader(program_, frag_shader); |
| 113 glLinkProgram(program_); |
| 114 |
| 115 // Schedule the first paint. |
| 116 g_idle_add(Widget::IdleRedraw, this); |
| 117 } |
| 118 |
| 119 Widget::~Widget() { |
| 120 wl_egl_window_destroy(window_.egl_window()); |
| 121 } |
| 122 |
| 123 void Widget::OnMotionNotify(base::wayland::WaylandEvent event) { |
| 124 // TODO(dnicoara) Need to add the icons for the cursors. |
| 125 if (event.motion.x > allocation_.width() * 0.75 || |
| 126 event.motion.x < allocation_.width() * 0.25 || |
| 127 event.motion.y > allocation_.height() * 0.75 || |
| 128 event.motion.y < allocation_.height() * 0.25) { |
| 129 // cursor_.ChangeCursor(ui::WaylandCursor::ARROW_CURSOR); |
| 130 LOG(INFO) << "ChangeCursor to arrow"; |
| 131 } else { |
| 132 // cursor_.ChangeCursor(ui::WaylandCursor::HAND_CURSOR); |
| 133 LOG(INFO) << "ChangeCursor to hand"; |
| 134 } |
| 135 } |
| 136 |
| 137 void Widget::OnButtonNotify(base::wayland::WaylandEvent event) { |
| 138 if (event.type == base::wayland::WAYLAND_BUTTON) |
| 139 LOG(INFO) << "Button: " << event.button.button; |
| 140 } |
| 141 |
| 142 void Widget::OnKeyNotify(base::wayland::WaylandEvent event) { |
| 143 // Simple example of keyboard interaction. On up/down keys we will change |
| 144 // the width of the window. |
| 145 switch (event.key.sym) { |
| 146 case XK_Up: |
| 147 allocation_.set_width(allocation_.width() + 20); |
| 148 break; |
| 149 case XK_Down: |
| 150 if (allocation_.width() > 20) |
| 151 allocation_.set_width(allocation_.width() - 20); |
| 152 break; |
| 153 case XK_Escape: |
| 154 g_main_loop_quit(g_loop); |
| 155 return; |
| 156 default: |
| 157 break; |
| 158 } |
| 159 |
| 160 // Perform the resize and schedule a new paint. |
| 161 wl_egl_window_resize(window_.egl_window(), |
| 162 allocation_.width(), |
| 163 allocation_.height(), |
| 164 0, 0); |
| 165 g_idle_add(Widget::IdleRedraw, this); |
| 166 } |
| 167 |
| 168 void Widget::OnPointerFocus(base::wayland::WaylandEvent event) { |
| 169 } |
| 170 |
| 171 void Widget::OnKeyboardFocus(base::wayland::WaylandEvent event) { |
| 172 } |
| 173 |
| 174 void Widget::OnGeometryChange(base::wayland::WaylandEvent event) { |
| 175 g_idle_add(Widget::IdleRedraw, this); |
| 176 } |
| 177 |
| 178 // static |
| 179 gboolean Widget::IdleRedraw(void* data) { |
| 180 static_cast<Widget*>(data)->Redraw(); |
| 181 return FALSE; |
| 182 } |
| 183 |
| 184 void Widget::Redraw() { |
| 185 // Draw a rectangle in the middle of the window. |
| 186 static const GLfloat kVertices[] = { |
| 187 0.5, 0.5, 0.0, |
| 188 -0.5, 0.5, 0.0, |
| 189 -0.5, -0.5, 0.0, |
| 190 0.5, -0.5, 0.0 |
| 191 }; |
| 192 |
| 193 glViewport(allocation_.x(), allocation_.y(), |
| 194 allocation_.width(), allocation_.height()); |
| 195 glClearColor(0.5, 0.0, 0.0, 0.5); |
| 196 glClear(GL_COLOR_BUFFER_BIT); |
| 197 |
| 198 glUseProgram(program_); |
| 199 |
| 200 GLuint vert_location = glGetAttribLocation(program_, "vPosition"); |
| 201 glVertexAttribPointer(vert_location, 3, GL_FLOAT, GL_FALSE, 0, kVertices); |
| 202 glEnableVertexAttribArray(vert_location); |
| 203 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
| 204 |
| 205 glFlush(); |
| 206 surface_->SwapBuffers(); |
| 207 } |
| 208 |
| 209 } // namespace |
| 210 |
| 211 int main(int argc, char** argv) { |
| 212 CommandLine::Init(argc, argv); |
| 213 |
| 214 base::AtExitManager exit_manager; |
| 215 |
| 216 // Set the EGL platform to wayland otherwise it may think this is supposed to |
| 217 // run on X. |
| 218 setenv("EGL_PLATFORM", "wayland", 1); |
| 219 if (!gfx::GLSurface::InitializeOneOff()) { |
| 220 LOG(ERROR) << "Failed to initialize GLSurface"; |
| 221 return -1; |
| 222 } |
| 223 |
| 224 // Once EGL is initialized in the above step, get the Wayland display |
| 225 // associated with the native display. |
| 226 ui::WaylandDisplay* display = ui::WaylandDisplay::GetDisplay( |
| 227 gfx::GLSurfaceEGL::GetNativeDisplay()); |
| 228 |
| 229 // Create a Wayland message pump. This will take care of processing the |
| 230 // Wayland events. |
| 231 base::MessagePumpWayland pump; |
| 232 |
| 233 // Create our sample widget. |
| 234 Widget widget(display); |
| 235 |
| 236 g_main_loop_run(g_loop); |
| 237 g_main_loop_unref(g_loop); |
| 238 return 0; |
| 239 } |
OLD | NEW |