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 |