| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 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 // This is a test application for gl_helper.*, which draws directly to a native | |
| 6 // viewport (without using the view manager). | |
| 7 | |
| 8 #include <GLES2/gl2.h> | |
| 9 #include <math.h> | |
| 10 | |
| 11 #include "apps/moterm/gl_helper.h" | |
| 12 #include "base/bind.h" | |
| 13 #include "base/logging.h" | |
| 14 #include "base/macros.h" | |
| 15 #include "base/memory/scoped_ptr.h" | |
| 16 #include "mojo/application/application_runner_chromium.h" | |
| 17 #include "mojo/public/c/system/main.h" | |
| 18 #include "mojo/public/cpp/application/application_impl.h" | |
| 19 #include "mojo/services/geometry/interfaces/geometry.mojom.h" | |
| 20 #include "mojo/services/gpu/interfaces/context_provider.mojom.h" | |
| 21 #include "mojo/services/native_viewport/interfaces/native_viewport.mojom.h" | |
| 22 #include "mojo/services/surfaces/interfaces/display.mojom.h" | |
| 23 #include "mojo/services/surfaces/interfaces/quads.mojom.h" | |
| 24 #include "mojo/services/surfaces/interfaces/surfaces.mojom.h" | |
| 25 | |
| 26 namespace { | |
| 27 | |
| 28 GLuint LoadShader(GLenum type, const char* shader_source) { | |
| 29 GLuint shader = glCreateShader(type); | |
| 30 CHECK(shader); | |
| 31 glShaderSource(shader, 1, &shader_source, nullptr); | |
| 32 glCompileShader(shader); | |
| 33 GLint compiled = 0; | |
| 34 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); | |
| 35 CHECK(compiled); | |
| 36 return shader; | |
| 37 } | |
| 38 | |
| 39 class GlHelperExampleApp : public mojo::ApplicationDelegate, | |
| 40 public GlHelper::Client { | |
| 41 public: | |
| 42 GlHelperExampleApp() | |
| 43 : application_impl_(), | |
| 44 program_(0), | |
| 45 transform_location_(0), | |
| 46 scale_location_(0), | |
| 47 framebuffer_(0), | |
| 48 vertex_buffer_(0), | |
| 49 draw_number_(0) {} | |
| 50 ~GlHelperExampleApp() override {} | |
| 51 | |
| 52 private: | |
| 53 void OnViewportMetricsReceived(mojo::ViewportMetricsPtr metrics) { | |
| 54 DVLOG(1) << "Viewport metrics received: size = " << metrics->size->width | |
| 55 << "x" << metrics->size->height | |
| 56 << ", device_pixel_ratio = " << metrics->device_pixel_ratio; | |
| 57 | |
| 58 if (metrics->size->width != viewport_size_.width || | |
| 59 metrics->size->height != viewport_size_.height) { | |
| 60 viewport_size_ = *metrics->size; | |
| 61 gl_helper_->SetSurfaceSize(viewport_size_); | |
| 62 } | |
| 63 | |
| 64 native_viewport_->RequestMetrics( | |
| 65 base::Bind(&GlHelperExampleApp::OnViewportMetricsReceived, | |
| 66 base::Unretained(this))); | |
| 67 } | |
| 68 | |
| 69 void InitGlState() { | |
| 70 static const char vertex_shader_source[] = | |
| 71 "attribute vec4 position; \n" | |
| 72 "uniform mat4 transform; \n" | |
| 73 "uniform vec4 scale; \n" | |
| 74 "void main() { \n" | |
| 75 " gl_Position = (position * transform) * scale; \n" | |
| 76 "} \n"; | |
| 77 static const char fragment_shader_source[] = | |
| 78 "precision mediump float; \n" | |
| 79 "void main() { \n" | |
| 80 " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n" | |
| 81 "} \n"; | |
| 82 static const float vertices[] = { | |
| 83 0.f, 0.5f, -sqrtf(5.f) / 4.f, -0.25f, sqrtf(5.f) / 4.f, -0.25f}; | |
| 84 GLuint vertex_shader = LoadShader(GL_VERTEX_SHADER, vertex_shader_source); | |
| 85 GLuint fragment_shader = | |
| 86 LoadShader(GL_FRAGMENT_SHADER, fragment_shader_source); | |
| 87 program_ = glCreateProgram(); | |
| 88 CHECK(program_); | |
| 89 glAttachShader(program_, vertex_shader); | |
| 90 glAttachShader(program_, fragment_shader); | |
| 91 glBindAttribLocation(program_, kPositionLocation, "position"); | |
| 92 glLinkProgram(program_); | |
| 93 glDeleteShader(vertex_shader); | |
| 94 glDeleteShader(fragment_shader); | |
| 95 GLint linked = 0; | |
| 96 glGetProgramiv(program_, GL_LINK_STATUS, &linked); | |
| 97 CHECK(linked); | |
| 98 transform_location_ = glGetUniformLocation(program_, "transform"); | |
| 99 CHECK_NE(transform_location_, -1); | |
| 100 scale_location_ = glGetUniformLocation(program_, "scale"); | |
| 101 CHECK_NE(scale_location_, -1); | |
| 102 | |
| 103 glGenFramebuffers(1, &framebuffer_); | |
| 104 CHECK(framebuffer_); | |
| 105 | |
| 106 glGenBuffers(1, &vertex_buffer_); | |
| 107 CHECK(vertex_buffer_); | |
| 108 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); | |
| 109 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); | |
| 110 | |
| 111 glClearColor(0.f, 1.f, 0.f, 1.f); | |
| 112 } | |
| 113 | |
| 114 void Draw() { | |
| 115 DCHECK(gl_helper_); | |
| 116 | |
| 117 gl_helper_->StartFrame(); | |
| 118 | |
| 119 if (!program_) | |
| 120 InitGlState(); | |
| 121 | |
| 122 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_); | |
| 123 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | |
| 124 gl_helper_->GetFrameTexture(), 0); | |
| 125 glViewport(0, 0, viewport_size_.width, viewport_size_.height); | |
| 126 | |
| 127 glClear(GL_COLOR_BUFFER_BIT); | |
| 128 | |
| 129 glUseProgram(program_); | |
| 130 | |
| 131 float angle = static_cast<float>(draw_number_ % 360) * M_PI / 180; | |
| 132 float transform[4][4] = {{cosf(angle), sinf(angle), 0.f, 0.f}, | |
| 133 {-sinf(angle), cosf(angle), 0.f, 0.f}, | |
| 134 {0.f, 0.f, 1.f, 0.f}, | |
| 135 {0.f, 0.f, 0.f, 1.f}}; | |
| 136 glUniformMatrix4fv(transform_location_, 1, GL_FALSE, &transform[0][0]); | |
| 137 if (viewport_size_.width >= viewport_size_.height) { | |
| 138 glUniform4f(scale_location_, static_cast<float>(viewport_size_.height) / | |
| 139 static_cast<float>(viewport_size_.width), | |
| 140 1.f, 1.f, 1.f); | |
| 141 } else { | |
| 142 glUniform4f(scale_location_, 1.f, | |
| 143 static_cast<float>(viewport_size_.width) / | |
| 144 static_cast<float>(viewport_size_.height), | |
| 145 1.f, 1.f); | |
| 146 } | |
| 147 | |
| 148 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); | |
| 149 glVertexAttribPointer(kPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0); | |
| 150 glEnableVertexAttribArray(kPositionLocation); | |
| 151 glDrawArrays(GL_TRIANGLES, 0, 3); | |
| 152 | |
| 153 gl_helper_->EndFrame(); | |
| 154 | |
| 155 draw_number_++; | |
| 156 } | |
| 157 | |
| 158 void SubmitFrame() { | |
| 159 DCHECK(surface_id_.local); | |
| 160 DCHECK(surface_id_.id_namespace); | |
| 161 | |
| 162 mojo::FramePtr frame = mojo::Frame::New(); | |
| 163 frame->resources = mojo::Array<mojo::TransferableResourcePtr>::New(0); | |
| 164 frame->passes = mojo::Array<mojo::PassPtr>::New(1); | |
| 165 mojo::PassPtr pass = mojo::Pass::New(); | |
| 166 pass->id = 0; | |
| 167 mojo::Rect viewport_rect; | |
| 168 viewport_rect.width = viewport_size_.width; | |
| 169 viewport_rect.height = viewport_size_.height; | |
| 170 pass->output_rect = viewport_rect.Clone(); | |
| 171 pass->damage_rect = viewport_rect.Clone(); | |
| 172 mojo::Transform identity_transform; | |
| 173 identity_transform.matrix = mojo::Array<float>::New(16); | |
| 174 for (size_t i = 0; i < 4; i++) { | |
| 175 for (size_t j = 0; j < 4; j++) | |
| 176 identity_transform.matrix[4 * i + j] = (i == j); | |
| 177 } | |
| 178 pass->transform_to_root_target = identity_transform.Clone(); | |
| 179 pass->has_transparent_background = false; | |
| 180 pass->quads = mojo::Array<mojo::QuadPtr>::New(1); | |
| 181 mojo::QuadPtr quad = mojo::Quad::New(); | |
| 182 quad->material = mojo::Material::SURFACE_CONTENT; | |
| 183 quad->rect = viewport_rect.Clone(); | |
| 184 quad->opaque_rect = viewport_rect.Clone(); | |
| 185 quad->visible_rect = viewport_rect.Clone(); | |
| 186 quad->needs_blending = false; | |
| 187 quad->shared_quad_state_index = 0; | |
| 188 mojo::SurfaceQuadStatePtr surface_quad_state = | |
| 189 mojo::SurfaceQuadState::New(); | |
| 190 surface_quad_state->surface = surface_id_.Clone(); | |
| 191 quad->surface_quad_state = surface_quad_state.Pass(); | |
| 192 | |
| 193 pass->quads[0] = quad.Pass(); | |
| 194 pass->shared_quad_states = mojo::Array<mojo::SharedQuadStatePtr>::New(1); | |
| 195 mojo::SharedQuadStatePtr shared_quad_state = mojo::SharedQuadState::New(); | |
| 196 shared_quad_state->content_to_target_transform = identity_transform.Clone(); | |
| 197 shared_quad_state->content_bounds = viewport_size_.Clone(); | |
| 198 shared_quad_state->visible_content_rect = viewport_rect.Clone(); | |
| 199 shared_quad_state->clip_rect = viewport_rect.Clone(); | |
| 200 shared_quad_state->is_clipped = false; | |
| 201 shared_quad_state->opacity = 1; | |
| 202 shared_quad_state->blend_mode = mojo::SkXfermode::kSrc_Mode; | |
| 203 shared_quad_state->sorting_context_id = 0; | |
| 204 pass->shared_quad_states[0] = shared_quad_state.Pass(); | |
| 205 frame->passes[0] = pass.Pass(); | |
| 206 | |
| 207 DCHECK(display_); | |
| 208 display_->SubmitFrame(frame.Pass(), mojo::Display::SubmitFrameCallback()); | |
| 209 } | |
| 210 | |
| 211 // |mojo::ApplicationDelegate|: | |
| 212 void Initialize(mojo::ApplicationImpl* application_impl) override { | |
| 213 DCHECK(!application_impl_); | |
| 214 application_impl_ = application_impl; | |
| 215 | |
| 216 application_impl->ConnectToService("mojo:native_viewport_service", | |
| 217 &native_viewport_); | |
| 218 viewport_size_.width = 800; | |
| 219 viewport_size_.height = 600; | |
| 220 native_viewport_->Create( | |
| 221 viewport_size_.Clone(), mojo::SurfaceConfiguration::New(), | |
| 222 base::Bind(&GlHelperExampleApp::OnViewportMetricsReceived, | |
| 223 base::Unretained(this))); | |
| 224 native_viewport_->Show(); | |
| 225 | |
| 226 mojo::ContextProviderPtr context_provider; | |
| 227 native_viewport_->GetContextProvider(GetProxy(&context_provider)); | |
| 228 | |
| 229 mojo::DisplayFactoryPtr display_factory; | |
| 230 application_impl_->ConnectToService("mojo:surfaces_service", | |
| 231 &display_factory); | |
| 232 display_factory->Create(context_provider.Pass(), nullptr, | |
| 233 GetProxy(&display_)); | |
| 234 | |
| 235 gl_helper_.reset(new GlHelper(this, application_impl_->shell(), GL_RGBA, | |
| 236 false, viewport_size_)); | |
| 237 Draw(); | |
| 238 } | |
| 239 | |
| 240 // |GlHelper::Client|: | |
| 241 void OnSurfaceIdChanged(mojo::SurfaceIdPtr surface_id) override { | |
| 242 surface_id_ = *surface_id; | |
| 243 SubmitFrame(); | |
| 244 } | |
| 245 | |
| 246 void OnContextLost() override { CHECK(false) << "Oops, lost context."; } | |
| 247 | |
| 248 void OnFrameDisplayed(uint32_t frame_id) override { Draw(); } | |
| 249 | |
| 250 static const GLuint kPositionLocation = 0; | |
| 251 | |
| 252 mojo::ApplicationImpl* application_impl_; | |
| 253 mojo::NativeViewportPtr native_viewport_; | |
| 254 mojo::Size viewport_size_; | |
| 255 mojo::DisplayPtr display_; | |
| 256 scoped_ptr<GlHelper> gl_helper_; | |
| 257 | |
| 258 mojo::SurfaceId surface_id_; | |
| 259 | |
| 260 // GL-related state: | |
| 261 GLuint program_; | |
| 262 GLint transform_location_; | |
| 263 GLint scale_location_; | |
| 264 GLuint framebuffer_; | |
| 265 GLuint vertex_buffer_; | |
| 266 | |
| 267 uint64_t draw_number_; | |
| 268 | |
| 269 DISALLOW_COPY_AND_ASSIGN(GlHelperExampleApp); | |
| 270 }; | |
| 271 | |
| 272 const GLuint GlHelperExampleApp::kPositionLocation; | |
| 273 | |
| 274 } // namespace | |
| 275 | |
| 276 MojoResult MojoMain(MojoHandle application_request) { | |
| 277 mojo::ApplicationRunnerChromium runner(new GlHelperExampleApp()); | |
| 278 return runner.Run(application_request); | |
| 279 } | |
| OLD | NEW |