Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: apps/moterm/gl_helper.cc

Issue 1556683004: Port Moterm to Mozart. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-16
Patch Set: fix nits Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « apps/moterm/gl_helper.h ('k') | apps/moterm/gl_helper_test_app.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 #include "apps/moterm/gl_helper.h"
6
7 #ifndef GL_GLEXT_PROTOTYPES
8 #define GL_GLEXT_PROTOTYPES
9 #endif
10
11 #include <GLES2/gl2.h>
12 #include <GLES2/gl2extmojo.h>
13 #include <MGL/mgl.h>
14
15 #include "base/bind.h"
16 #include "base/location.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/task_runner.h"
19 #include "mojo/public/cpp/application/connect.h"
20 #include "mojo/public/interfaces/application/shell.mojom.h"
21 #include "mojo/services/geometry/cpp/geometry_util.h"
22 #include "mojo/services/surfaces/cpp/surfaces_utils.h"
23
24 // Maximum number of (live) textures to keep around.
25 const size_t kMaxTextures = 10;
26
27 GlHelper::GlHelper(Client* client,
28 mojo::Shell* shell,
29 GLint texture_format,
30 bool flipped,
31 const mojo::Size& initial_size)
32 : client_(client),
33 texture_format_(texture_format),
34 flipped_(flipped),
35 returner_binding_(this),
36 next_surface_size_(initial_size),
37 mgl_context_(MGL_NO_CONTEXT),
38 next_frame_id_(0),
39 frame_texture_(0),
40 id_namespace_(0),
41 local_id_(0),
42 next_resource_id_(0),
43 weak_factory_(this) {
44 mojo::ServiceProviderPtr native_viewport_service_provider;
45 shell->ConnectToApplication("mojo:native_viewport_service",
46 GetProxy(&native_viewport_service_provider),
47 nullptr);
48 mojo::ConnectToService(native_viewport_service_provider.get(), &gpu_);
49
50 mojo::ServiceProviderPtr surfaces_service_provider;
51 shell->ConnectToApplication("mojo:surfaces_service",
52 GetProxy(&surfaces_service_provider), nullptr);
53 mojo::ConnectToService(surfaces_service_provider.get(), &surface_);
54 surface_->GetIdNamespace(base::Bind(&GlHelper::GetIdNamespaceCallback,
55 weak_factory_.GetWeakPtr()));
56 mojo::ResourceReturnerPtr returner_ptr;
57 returner_binding_.Bind(GetProxy(&returner_ptr));
58 surface_->SetResourceReturner(returner_ptr.Pass());
59 }
60
61 GlHelper::~GlHelper() {
62 DCHECK(!frame_texture_);
63 if (mgl_context_ != MGL_NO_CONTEXT)
64 MGLDestroyContext(mgl_context_);
65 }
66
67 void GlHelper::SetSurfaceSize(const mojo::Size& surface_size) {
68 next_surface_size_ = surface_size;
69 }
70
71 void GlHelper::MakeCurrent() {
72 EnsureContext();
73 }
74
75 void GlHelper::StartFrame() {
76 DCHECK(!frame_texture_);
77
78 EnsureContext();
79 EnsureSurface();
80
81 TextureInfo texture_info = GetTexture();
82 DCHECK(texture_info.texture);
83 frame_texture_ = texture_info.texture;
84
85 // It's already bound.
86 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
87 }
88
89 uint32_t GlHelper::EndFrame() {
90 DCHECK(frame_texture_);
91
92 mojo::Rect size_rect;
93 size_rect.width = current_surface_size_.width;
94 size_rect.height = current_surface_size_.height;
95
96 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
97 glGenMailboxCHROMIUM(mailbox);
98 glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox);
99 GLuint sync_point = glInsertSyncPointCHROMIUM();
100
101 mojo::FramePtr frame = mojo::Frame::New();
102
103 // Frame resources:
104 frame->resources.push_back(mojo::TransferableResource::New());
105 mojo::TransferableResource* resource = frame->resources[0].get();
106 resource->id = next_resource_id_++;
107 textures_pending_return_.push_back(
108 TextureInfo(resource->id, frame_texture_, current_surface_size_));
109 frame_texture_ = 0;
110 // TODO(vtl): This is wrong, but doesn't seem to have an effect.
111 resource->format = mojo::ResourceFormat::RGBA_8888;
112 resource->filter = GL_LINEAR;
113 resource->size = current_surface_size_.Clone();
114 mojo::MailboxHolderPtr mailbox_holder = mojo::MailboxHolder::New();
115 mailbox_holder->mailbox = mojo::Mailbox::New();
116 for (int i = 0; i < GL_MAILBOX_SIZE_CHROMIUM; ++i)
117 mailbox_holder->mailbox->name.push_back(mailbox[i]);
118 mailbox_holder->texture_target = GL_TEXTURE_2D;
119 mailbox_holder->sync_point = sync_point;
120 resource->mailbox_holder = mailbox_holder.Pass();
121 resource->is_repeated = false;
122 resource->is_software = false;
123
124 // Frame passes:
125 frame->passes.push_back(mojo::CreateDefaultPass(1, size_rect));
126 mojo::Pass* pass = frame->passes[0].get();
127 pass->quads.push_back(mojo::Quad::New());
128 mojo::Quad* quad = pass->quads[0].get();
129 quad->material = mojo::Material::TEXTURE_CONTENT;
130 quad->rect = size_rect.Clone();
131 quad->opaque_rect = size_rect.Clone();
132 quad->visible_rect = size_rect.Clone();
133 quad->needs_blending = true;
134 quad->shared_quad_state_index = 0;
135 quad->texture_quad_state = mojo::TextureQuadState::New();
136 mojo::TextureQuadState* texture_state = quad->texture_quad_state.get();
137 texture_state->resource_id = resource->id;
138 texture_state->premultiplied_alpha = true;
139 texture_state->uv_top_left = mojo::PointF::New();
140 texture_state->uv_bottom_right = mojo::PointF::New();
141 texture_state->uv_bottom_right->x = 1.f;
142 texture_state->uv_bottom_right->y = 1.f;
143 texture_state->background_color = mojo::Color::New();
144 texture_state->background_color->rgba = 0;
145 for (int i = 0; i < 4; ++i)
146 texture_state->vertex_opacity.push_back(1.f);
147 texture_state->flipped = flipped_;
148 pass->shared_quad_states.push_back(
149 mojo::CreateDefaultSQS(current_surface_size_));
150
151 surface_->SubmitFrame(local_id_, frame.Pass(),
152 base::Bind(&GlHelper::SubmitFrameCallback,
153 weak_factory_.GetWeakPtr(), next_frame_id_));
154
155 return next_frame_id_++;
156 }
157
158 GLuint GlHelper::GetFrameTexture() {
159 DCHECK(frame_texture_);
160 return frame_texture_;
161 }
162
163 void GlHelper::ReturnResources(
164 mojo::Array<mojo::ReturnedResourcePtr> resources) {
165 DCHECK(!frame_texture_);
166
167 if (mgl_context_ == MGL_NO_CONTEXT) {
168 DCHECK(textures_pending_return_.empty());
169 return;
170 }
171
172 MGLMakeCurrent(mgl_context_);
173
174 // Note: This quadratic nested loop is OK, since we expect both |resources|
175 // and |textures_pending_return_| to be small (and |resources| should
176 // usually have just a single element).
177 for (size_t i = 0; i < resources.size(); ++i) {
178 mojo::ReturnedResourcePtr resource = resources[i].Pass();
179 DCHECK_EQ(resource->count, 1);
180
181 bool found = false;
182 for (size_t j = 0; j < textures_pending_return_.size(); j++) {
183 const TextureInfo& texture_info = textures_pending_return_[j];
184 if (texture_info.resource_id == resource->id) {
185 glWaitSyncPointCHROMIUM(resource->sync_point);
186 ReturnTexture(texture_info);
187 textures_pending_return_.erase(textures_pending_return_.begin() + j);
188 found = true;
189 break;
190 }
191 }
192 if (!found) {
193 // If we don't texture ID for it, assume we lost the context.
194 // TODO(vtl): This may leak (but currently we don't know if the texture is
195 // still valid).
196 DVLOG(1) << "Returned texture not found (context lost?)";
197 }
198 }
199 }
200
201 void GlHelper::EnsureContext() {
202 DCHECK(!frame_texture_);
203
204 if (mgl_context_ == MGL_NO_CONTEXT) {
205 DCHECK(textures_pending_return_.empty());
206
207 mojo::CommandBufferPtr command_buffer;
208 gpu_->CreateOffscreenGLES2Context(mojo::GetProxy(&command_buffer));
209 mgl_context_ = MGLCreateContext(
210 MGL_API_VERSION_GLES2,
211 command_buffer.PassInterface().PassHandle().release().value(), nullptr,
212 &GlHelper::OnContextLostThunk, this,
213 mojo::Environment::GetDefaultAsyncWaiter());
214 CHECK_NE(mgl_context_, MGL_NO_CONTEXT);
215 }
216
217 MGLMakeCurrent(mgl_context_);
218 }
219
220 void GlHelper::EnsureSurface() {
221 DCHECK(!frame_texture_);
222 DCHECK_NE(mgl_context_, MGL_NO_CONTEXT);
223
224 if (local_id_) {
225 if (current_surface_size_ == next_surface_size_)
226 return;
227
228 surface_->DestroySurface(local_id_);
229
230 ClearTextures();
231 }
232
233 local_id_++;
234 surface_->CreateSurface(local_id_);
235 current_surface_size_ = next_surface_size_;
236 if (id_namespace_) {
237 // Don't call the client in the nested context.
238 base::MessageLoop::current()->task_runner()->PostTask(
239 FROM_HERE, base::Bind(&GlHelper::CallOnSurfaceIdChanged,
240 weak_factory_.GetWeakPtr()));
241 }
242 }
243
244 void GlHelper::CallOnSurfaceIdChanged() {
245 DCHECK(id_namespace_ && local_id_);
246
247 auto qualified_id = mojo::SurfaceId::New();
248 qualified_id->id_namespace = id_namespace_;
249 qualified_id->local = local_id_;
250 client_->OnSurfaceIdChanged(qualified_id.Pass());
251 }
252
253 GlHelper::TextureInfo GlHelper::GetTexture() {
254 DCHECK_NE(mgl_context_, MGL_NO_CONTEXT);
255
256 if (!textures_.empty()) {
257 TextureInfo rv = textures_.front();
258 DCHECK(rv.size == current_surface_size_);
259 textures_.pop_front();
260 glBindTexture(GL_TEXTURE_2D, rv.texture);
261 return rv;
262 }
263
264 GLuint texture = 0;
265 glGenTextures(1, &texture);
266 DCHECK(texture);
267 glBindTexture(GL_TEXTURE_2D, texture);
268 glTexImage2D(GL_TEXTURE_2D, 0, texture_format_, current_surface_size_.width,
269 current_surface_size_.height, 0, texture_format_,
270 GL_UNSIGNED_BYTE, nullptr);
271
272 return TextureInfo(0, texture, current_surface_size_);
273 }
274
275 void GlHelper::ReturnTexture(const TextureInfo& texture_info) {
276 DCHECK_NE(mgl_context_, MGL_NO_CONTEXT);
277 DCHECK_NE(texture_info.texture, 0u);
278
279 if (texture_info.size == current_surface_size_ &&
280 textures_.size() < kMaxTextures)
281 textures_.push_back(texture_info); // TODO(vtl): Is |push_front()| better?
282 else
283 glDeleteTextures(1, &texture_info.texture);
284 }
285
286 void GlHelper::ClearTextures() {
287 DCHECK_NE(mgl_context_, MGL_NO_CONTEXT);
288
289 for (const auto& texture_info : textures_)
290 glDeleteTextures(1, &texture_info.texture);
291
292 textures_.clear();
293 }
294
295 void GlHelper::GetIdNamespaceCallback(uint32_t id_namespace) {
296 id_namespace_ = id_namespace;
297 if (local_id_) {
298 // We're in a callback, so we can just call the client directly.
299 CallOnSurfaceIdChanged();
300 }
301 }
302
303 // static
304 void GlHelper::OnContextLostThunk(void* self) {
305 static_cast<GlHelper*>(self)->OnContextLost();
306 }
307
308 void GlHelper::OnContextLost() {
309 // We shouldn't get this while we're processing a frame.
310 DCHECK(!frame_texture_);
311
312 DCHECK_NE(mgl_context_, MGL_NO_CONTEXT);
313 MGLDestroyContext(mgl_context_);
314 mgl_context_ = MGL_NO_CONTEXT;
315
316 // TODO(vtl): We don't know if any of those textures will be valid when
317 // returned (if they are), so assume they aren't.
318 textures_pending_return_.clear();
319
320 // We're in a callback, so we can just call the client directly.
321 client_->OnContextLost();
322 }
323
324 void GlHelper::SubmitFrameCallback(uint32_t frame_id) {
325 // We're in a callback, so we can just call the client directly.
326 client_->OnFrameDisplayed(frame_id);
327 }
OLDNEW
« no previous file with comments | « apps/moterm/gl_helper.h ('k') | apps/moterm/gl_helper_test_app.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698