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

Side by Side Diff: ui/gfx/compositor/compositor_gl.cc

Issue 7552039: Vend common GL context (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address reviewer comments. Created 9 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « ui/gfx/compositor/compositor_gl.h ('k') | ui/gfx/compositor/compositor_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/compositor/compositor_gl.h" 5 #include "ui/gfx/compositor/compositor_gl.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 }; 77 };
78 78
79 class TextureProgramSwizzleGL : public ui::TextureProgramGL { 79 class TextureProgramSwizzleGL : public ui::TextureProgramGL {
80 public: 80 public:
81 TextureProgramSwizzleGL() {} 81 TextureProgramSwizzleGL() {}
82 virtual bool Initialize(); 82 virtual bool Initialize();
83 private: 83 private:
84 DISALLOW_COPY_AND_ASSIGN(TextureProgramSwizzleGL); 84 DISALLOW_COPY_AND_ASSIGN(TextureProgramSwizzleGL);
85 }; 85 };
86 86
87 // We share between compositor contexts so that we don't have to compile
88 // shaders if they have already been compiled in another context.
89 class SharedResources {
90 public:
91 static SharedResources* GetInstance();
92
93 // Creates a context with shaders active.
94 scoped_refptr<gfx::GLContext> CreateContext(gfx::GLSurface* surface);
95 void ContextDestroyed();
96
97 ui::TextureProgramGL* program_no_swizzle() {
98 return program_no_swizzle_.get();
99 }
100
101 ui::TextureProgramGL* program_swizzle() { return program_swizzle_.get(); }
102
103 private:
104 friend struct DefaultSingletonTraits<SharedResources>;
105
106 SharedResources();
107 virtual ~SharedResources();
108
109 scoped_refptr<gfx::GLShareGroup> share_group_;
110 scoped_ptr<ui::TextureProgramGL> program_swizzle_;
111 scoped_ptr<ui::TextureProgramGL> program_no_swizzle_;
112
113 DISALLOW_COPY_AND_ASSIGN(SharedResources);
114 };
115
116 GLuint CompileShader(GLenum type, const GLchar* source) { 87 GLuint CompileShader(GLenum type, const GLchar* source) {
117 GLuint shader = glCreateShader(type); 88 GLuint shader = glCreateShader(type);
118 if (!shader) 89 if (!shader)
119 return 0; 90 return 0;
120 91
121 glShaderSource(shader, 1, &source, 0); 92 glShaderSource(shader, 1, &source, 0);
122 glCompileShader(shader); 93 glCompileShader(shader);
123 94
124 GLint compiled; 95 GLint compiled;
125 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 96 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 " gl_FragColor = texture2D(u_tex, v_texCoord).zyxw;" 139 " gl_FragColor = texture2D(u_tex, v_texCoord).zyxw;"
169 "}"; 140 "}";
170 141
171 frag_shader_ = CompileShader(GL_FRAGMENT_SHADER, frag_shader_source); 142 frag_shader_ = CompileShader(GL_FRAGMENT_SHADER, frag_shader_source);
172 if (!frag_shader_) 143 if (!frag_shader_)
173 return false; 144 return false;
174 145
175 return InitializeCommon(); 146 return InitializeCommon();
176 } 147 }
177 148
178 SharedResources::SharedResources() {
179 }
180
181 SharedResources::~SharedResources() {
182 }
183
184 // static
185 SharedResources* SharedResources::GetInstance() {
186 return Singleton<SharedResources>::get();
187 }
188
189 scoped_refptr<gfx::GLContext> SharedResources::CreateContext(
190 gfx::GLSurface* surface) {
191 if (share_group_.get()) {
192 return gfx::GLContext::CreateGLContext(share_group_.get(), surface);
193 } else {
194 scoped_refptr<gfx::GLContext> context(
195 gfx::GLContext::CreateGLContext(NULL, surface));
196 context->MakeCurrent(surface);
197
198 if (!program_no_swizzle_.get()) {
199 scoped_ptr<ui::TextureProgramGL> temp_program(
200 new TextureProgramNoSwizzleGL());
201 if (!temp_program->Initialize()) {
202 LOG(ERROR) << "Unable to initialize shaders (context = "
203 << static_cast<void*>(context.get()) << ")";
204 return NULL;
205 }
206 program_no_swizzle_.swap(temp_program);
207 }
208
209 if (!program_swizzle_.get()) {
210 scoped_ptr<ui::TextureProgramGL> temp_program(
211 new TextureProgramSwizzleGL());
212 if (!temp_program->Initialize()) {
213 LOG(ERROR) << "Unable to initialize shaders (context = "
214 << static_cast<void*>(context.get()) << ")";
215 return NULL;
216 }
217 program_swizzle_.swap(temp_program);
218 }
219
220 share_group_ = context->share_group();
221 return context;
222 }
223 }
224
225 void SharedResources::ContextDestroyed() {
226 if (share_group_.get() && share_group_->GetHandle() == NULL) {
227 share_group_ = NULL;
228 program_no_swizzle_.reset();
229 program_swizzle_.reset();
230 }
231 }
232
233 } // namespace 149 } // namespace
234 150
235 namespace ui { 151 namespace ui {
236 152
237 TextureProgramGL::TextureProgramGL() 153 TextureProgramGL::TextureProgramGL()
238 : program_(0), 154 : program_(0),
239 a_pos_loc_(0), 155 a_pos_loc_(0),
240 a_tex_loc_(0), 156 a_tex_loc_(0),
241 u_tex_loc_(0), 157 u_tex_loc_(0),
242 u_mat_loc_(0) { 158 u_mat_loc_(0) {
(...skipping 25 matching lines...) Expand all
268 184
269 // Store locations of program inputs. 185 // Store locations of program inputs.
270 a_pos_loc_ = glGetAttribLocation(program_, "a_position"); 186 a_pos_loc_ = glGetAttribLocation(program_, "a_position");
271 a_tex_loc_ = glGetAttribLocation(program_, "a_texCoord"); 187 a_tex_loc_ = glGetAttribLocation(program_, "a_texCoord");
272 u_tex_loc_ = glGetUniformLocation(program_, "u_tex"); 188 u_tex_loc_ = glGetUniformLocation(program_, "u_tex");
273 u_mat_loc_ = glGetUniformLocation(program_, "u_matViewProjection"); 189 u_mat_loc_ = glGetUniformLocation(program_, "u_matViewProjection");
274 190
275 return true; 191 return true;
276 } 192 }
277 193
278 TextureGL::TextureGL(CompositorGL* compositor) : texture_id_(0), 194 SharedResources::SharedResources() : initialized_(false) {
279 compositor_(compositor) {
280 } 195 }
281 196
282 TextureGL::TextureGL(CompositorGL* compositor, 197
283 const gfx::Size& size) 198 SharedResources::~SharedResources() {
284 : texture_id_(0), 199 }
285 size_(size), 200
286 compositor_(compositor) { 201 // static
202 SharedResources* SharedResources::GetInstance() {
203 // We use LeakySingletonTraits so that we don't race with
204 // the tear down of the gl_bindings.
205 SharedResources* instance = Singleton<SharedResources,
206 LeakySingletonTraits<SharedResources> >::get();
207 if (instance->Initialize()) {
208 return instance;
209 } else {
210 instance->Destroy();
211 return NULL;
212 }
213 }
214
215 bool SharedResources::Initialize() {
216 if (initialized_)
217 return true;
218
219 {
220 // The following line of code exists soley to disable IO restrictions
221 // on this thread long enough to perform the GL bindings.
222 // TODO(wjmaclean) Remove this when GL initialisation cleaned up.
223 base::ThreadRestrictions::ScopedAllowIO allow_io;
224 if (!gfx::GLSurface::InitializeOneOff() ||
225 gfx::GetGLImplementation() == gfx::kGLImplementationNone) {
226 LOG(ERROR) << "Could not load the GL bindings";
227 return false;
228 }
229 }
230
231 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1));
232 if (!surface_.get()) {
233 LOG(ERROR) << "Unable to create offscreen GL surface.";
234 return false;
235 }
236
237 context_ = gfx::GLContext::CreateGLContext(NULL, surface_.get());
238 if (!context_.get()) {
239 LOG(ERROR) << "Unable to create GL context.";
240 return false;
241 }
242
243 program_no_swizzle_.reset();
244 program_swizzle_.reset();
245
246 context_->MakeCurrent(surface_.get());
247
248 scoped_ptr<ui::TextureProgramGL> temp_program_no_swizzle(
249 new TextureProgramNoSwizzleGL());
250 if (!temp_program_no_swizzle->Initialize()) {
251 LOG(ERROR) << "Unable to initialize shader.";
252 return false;
253 }
254
255 scoped_ptr<ui::TextureProgramGL> temp_program_swizzle(
256 new TextureProgramSwizzleGL());
257 if (!temp_program_swizzle->Initialize()) {
258 LOG(ERROR) << "Unable to initialize shader.";
259 return false;
260 }
261
262 program_no_swizzle_.swap(temp_program_no_swizzle);
263 program_swizzle_.swap(temp_program_swizzle);
264
265 initialized_ = true;
266 return true;
267 }
268
269 void SharedResources::Destroy() {
270 program_swizzle_.reset();
271 program_no_swizzle_.reset();
272
273 context_ = NULL;
274 surface_ = NULL;
275
276 initialized_ = false;
277 }
278
279 bool SharedResources::MakeSharedContextCurrent() {
280 if (!initialized_)
281 return false;
282 else
283 return context_->MakeCurrent(surface_.get());
284 }
285
286 scoped_refptr<gfx::GLContext> SharedResources::CreateContext(
287 gfx::GLSurface* surface) {
288 if (initialized_)
289 return gfx::GLContext::CreateGLContext(context_->share_group(), surface);
290 else
291 return NULL;
292 }
293
294 TextureGL::TextureGL() : texture_id_(0) {
295 }
296
297 TextureGL::TextureGL(const gfx::Size& size) : texture_id_(0), size_(size) {
287 } 298 }
288 299
289 TextureGL::~TextureGL() { 300 TextureGL::~TextureGL() {
290 if (texture_id_) { 301 if (texture_id_) {
291 compositor_->MakeCurrent(); 302 SharedResources* instance = SharedResources::GetInstance();
303 DCHECK(instance);
304 instance->MakeSharedContextCurrent();
292 glDeleteTextures(1, &texture_id_); 305 glDeleteTextures(1, &texture_id_);
293 } 306 }
294 } 307 }
295 308
296 void TextureGL::SetCanvas(const SkCanvas& canvas, 309 void TextureGL::SetCanvas(const SkCanvas& canvas,
297 const gfx::Point& origin, 310 const gfx::Point& origin,
298 const gfx::Size& overall_size) { 311 const gfx::Size& overall_size) {
299 const SkBitmap& bitmap = canvas.getDevice()->accessBitmap(false); 312 const SkBitmap& bitmap = canvas.getDevice()->accessBitmap(false);
300 // Verify bitmap pixels are contiguous. 313 // Verify bitmap pixels are contiguous.
301 DCHECK_EQ(bitmap.rowBytes(), 314 DCHECK_EQ(bitmap.rowBytes(),
(...skipping 24 matching lines...) Expand all
326 GL_RGBA, GL_UNSIGNED_BYTE, pixels); 339 GL_RGBA, GL_UNSIGNED_BYTE, pixels);
327 } else { // Uploading partial texture. 340 } else { // Uploading partial texture.
328 glBindTexture(GL_TEXTURE_2D, texture_id_); 341 glBindTexture(GL_TEXTURE_2D, texture_id_);
329 glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x(), origin.y(), 342 glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x(), origin.y(),
330 bitmap.width(), bitmap.height(), 343 bitmap.width(), bitmap.height(),
331 GL_RGBA, GL_UNSIGNED_BYTE, pixels); 344 GL_RGBA, GL_UNSIGNED_BYTE, pixels);
332 } 345 }
333 } 346 }
334 347
335 void TextureGL::Draw(const ui::TextureDrawParams& params) { 348 void TextureGL::Draw(const ui::TextureDrawParams& params) {
336 DCHECK(compositor_->program_swizzle());
337 Draw(params, gfx::Rect(0, 0, size_.width(), size_.height())); 349 Draw(params, gfx::Rect(0, 0, size_.width(), size_.height()));
338 } 350 }
339 351
340 void TextureGL::Draw(const ui::TextureDrawParams& params, 352 void TextureGL::Draw(const ui::TextureDrawParams& params,
341 const gfx::Rect& clip_bounds_in_texture) { 353 const gfx::Rect& clip_bounds_in_texture) {
342 DCHECK(compositor_->program_swizzle()); 354 SharedResources* instance = SharedResources::GetInstance();
343 DrawInternal(*compositor_->program_swizzle(), params, clip_bounds_in_texture); 355 DCHECK(instance);
356 DrawInternal(*instance->program_swizzle(),
357 params,
358 clip_bounds_in_texture);
344 } 359 }
360
345 void TextureGL::DrawInternal(const ui::TextureProgramGL& program, 361 void TextureGL::DrawInternal(const ui::TextureProgramGL& program,
346 const ui::TextureDrawParams& params, 362 const ui::TextureDrawParams& params,
347 const gfx::Rect& clip_bounds_in_texture) { 363 const gfx::Rect& clip_bounds_in_texture) {
348 // clip clip_bounds_in_layer to size of texture 364 // Clip clip_bounds_in_texture to size of texture.
349 gfx::Rect clip_bounds = clip_bounds_in_texture.Intersect( 365 gfx::Rect clip_bounds = clip_bounds_in_texture.Intersect(
350 gfx::Rect(gfx::Point(0, 0), size_)); 366 gfx::Rect(gfx::Point(0, 0), size_));
367
368 // Verify that compositor_size has been set.
369 DCHECK(params.compositor_size != gfx::Size(0,0));
351 370
352 if (params.blend) 371 if (params.blend)
353 glEnable(GL_BLEND); 372 glEnable(GL_BLEND);
354 else 373 else
355 glDisable(GL_BLEND); 374 glDisable(GL_BLEND);
356 375
357 program.Use(); 376 program.Use();
358 377
359 glActiveTexture(GL_TEXTURE0); 378 glActiveTexture(GL_TEXTURE0);
360 glUniform1i(program.u_tex_loc(), 0); 379 glUniform1i(program.u_tex_loc(), 0);
361 glBindTexture(GL_TEXTURE_2D, texture_id_); 380 glBindTexture(GL_TEXTURE_2D, texture_id_);
362 381
363 gfx::Size window_size = compositor_->GetSize();
364
365 ui::Transform t; 382 ui::Transform t;
366 t.ConcatTranslate(1, 1); 383 t.ConcatTranslate(1, 1);
367 t.ConcatScale(size_.width()/2.0f, size_.height()/2.0f); 384 t.ConcatScale(size_.width()/2.0f, size_.height()/2.0f);
368 t.ConcatTranslate(0, -size_.height()); 385 t.ConcatTranslate(0, -size_.height());
369 t.ConcatScale(1, -1); 386 t.ConcatScale(1, -1);
370 387
371 t.ConcatTransform(params.transform); // Add view transform. 388 t.ConcatTransform(params.transform); // Add view transform.
372 389
373 t.ConcatTranslate(0, -window_size.height()); 390 t.ConcatTranslate(0, -params.compositor_size.height());
374 t.ConcatScale(1, -1); 391 t.ConcatScale(1, -1);
375 t.ConcatTranslate(-window_size.width() / 2.0f, -window_size.height() / 2.0f); 392 t.ConcatTranslate(-params.compositor_size.width() / 2.0f,
376 t.ConcatScale(2.0f / window_size.width(), 2.0f / window_size.height()); 393 -params.compositor_size.height() / 2.0f);
394 t.ConcatScale(2.0f / params.compositor_size.width(),
395 2.0f / params.compositor_size.height());
377 396
378 GLfloat m[16]; 397 GLfloat m[16];
379 t.matrix().asColMajorf(m); 398 t.matrix().asColMajorf(m);
380 399
381 // TODO(pkotwicz) window_size != size_, fix this
382 SkRect texture_rect = SkRect::MakeXYWH( 400 SkRect texture_rect = SkRect::MakeXYWH(
383 clip_bounds.x(), 401 clip_bounds.x(),
384 clip_bounds.y(), 402 clip_bounds.y(),
385 clip_bounds.width(), 403 clip_bounds.width(),
386 clip_bounds.height()); 404 clip_bounds.height());
387 405
388 ui::Transform texture_rect_transform; 406 ui::Transform texture_rect_transform;
389 texture_rect_transform.ConcatScale(1.0f / size_.width(), 407 texture_rect_transform.ConcatScale(1.0f / size_.width(),
390 1.0f / size_.height()); 408 1.0f / size_.height());
391 SkMatrix texture_transform_matrix = texture_rect_transform.matrix(); 409 SkMatrix texture_transform_matrix = texture_rect_transform.matrix();
(...skipping 30 matching lines...) Expand all
422 glEnableVertexAttribArray(program.a_pos_loc()); 440 glEnableVertexAttribArray(program.a_pos_loc());
423 glEnableVertexAttribArray(program.a_tex_loc()); 441 glEnableVertexAttribArray(program.a_tex_loc());
424 442
425 glUniformMatrix4fv(program.u_mat_loc(), 1, GL_FALSE, m); 443 glUniformMatrix4fv(program.u_mat_loc(), 1, GL_FALSE, m);
426 444
427 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 445 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
428 } 446 }
429 447
430 CompositorGL::CompositorGL(gfx::AcceleratedWidget widget, 448 CompositorGL::CompositorGL(gfx::AcceleratedWidget widget,
431 const gfx::Size& size) 449 const gfx::Size& size)
432 : size_(size), 450 : Compositor(size),
433 started_(false) { 451 started_(false) {
434 gl_surface_ = gfx::GLSurface::CreateViewGLSurface(false, widget); 452 gl_surface_ = gfx::GLSurface::CreateViewGLSurface(false, widget);
435 gl_context_ = SharedResources::GetInstance()-> 453 gl_context_ = SharedResources::GetInstance()->
436 CreateContext(gl_surface_.get()); 454 CreateContext(gl_surface_.get());
437 gl_context_->MakeCurrent(gl_surface_.get()); 455 gl_context_->MakeCurrent(gl_surface_.get());
438 glColorMask(true, true, true, true); 456 glColorMask(true, true, true, true);
439 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 457 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
440 } 458 }
441 459
442 CompositorGL::~CompositorGL() { 460 CompositorGL::~CompositorGL() {
443 gl_context_ = NULL; 461 gl_context_ = NULL;
444 SharedResources::GetInstance()->ContextDestroyed();
445 } 462 }
446 463
447 void CompositorGL::MakeCurrent() { 464 void CompositorGL::MakeCurrent() {
448 gl_context_->MakeCurrent(gl_surface_.get()); 465 gl_context_->MakeCurrent(gl_surface_.get());
449 } 466 }
450 467
451 gfx::Size CompositorGL::GetSize() { 468 void CompositorGL::OnWidgetSizeChanged() {
452 return size_;
453 }
454
455 TextureProgramGL* CompositorGL::program_no_swizzle() {
456 return SharedResources::GetInstance()->program_no_swizzle();
457 }
458
459 TextureProgramGL* CompositorGL::program_swizzle() {
460 return SharedResources::GetInstance()->program_swizzle();
461 } 469 }
462 470
463 Texture* CompositorGL::CreateTexture() { 471 Texture* CompositorGL::CreateTexture() {
464 Texture* texture = new TextureGL(this); 472 Texture* texture = new TextureGL();
465 return texture; 473 return texture;
466 } 474 }
467 475
468 void CompositorGL::NotifyStart() { 476 void CompositorGL::NotifyStart() {
469 started_ = true; 477 started_ = true;
470 gl_context_->MakeCurrent(gl_surface_.get()); 478 gl_context_->MakeCurrent(gl_surface_.get());
471 glViewport(0, 0, size_.width(), size_.height()); 479 glViewport(0, 0, size().width(), size().height());
472 glColorMask(true, true, true, true); 480 glColorMask(true, true, true, true);
473 481
474 #if defined(DEBUG) 482 #if defined(DEBUG)
475 // Clear to 'psychedelic' purple to make it easy to spot un-rendered regions. 483 // Clear to 'psychedelic' purple to make it easy to spot un-rendered regions.
476 glClearColor(223.0 / 255, 0, 1, 1); 484 glClearColor(223.0 / 255, 0, 1, 1);
477 glClear(GL_COLOR_BUFFER_BIT); 485 glClear(GL_COLOR_BUFFER_BIT);
478 #endif 486 #endif
479 // Do not clear in release: root layer is responsible for drawing every pixel. 487 // Do not clear in release: root layer is responsible for drawing every pixel.
480 } 488 }
481 489
482 void CompositorGL::NotifyEnd() { 490 void CompositorGL::NotifyEnd() {
483 DCHECK(started_); 491 DCHECK(started_);
484 gl_surface_->SwapBuffers(); 492 gl_surface_->SwapBuffers();
485 started_ = false; 493 started_ = false;
486 } 494 }
487 495
488 void CompositorGL::Blur(const gfx::Rect& bounds) { 496 void CompositorGL::Blur(const gfx::Rect& bounds) {
489 NOTIMPLEMENTED(); 497 NOTIMPLEMENTED();
490 } 498 }
491 499
492 void CompositorGL::SchedulePaint() { 500 void CompositorGL::SchedulePaint() {
493 // TODO: X doesn't provide coalescing of regions, its left to the toolkit. 501 // TODO: X doesn't provide coalescing of regions, its left to the toolkit.
494 NOTIMPLEMENTED(); 502 NOTIMPLEMENTED();
495 } 503 }
496 504
497 void CompositorGL::OnWidgetSizeChanged(const gfx::Size& size) {
498 size_ = size;
499 }
500
501 // static 505 // static
502 Compositor* Compositor::Create(gfx::AcceleratedWidget widget, 506 Compositor* Compositor::Create(gfx::AcceleratedWidget widget,
503 const gfx::Size& size) { 507 const gfx::Size& size) {
504 // The following line of code exists soley to disable IO restrictions 508 if (SharedResources::GetInstance() == NULL)
505 // on this thread long enough to perform the GL bindings. 509 return NULL;
506 // TODO(wjmaclean) Remove this when GL initialisation cleaned up. 510 else
507 base::ThreadRestrictions::ScopedAllowIO allow_io;
508 if (gfx::GLSurface::InitializeOneOff() &&
509 gfx::GetGLImplementation() != gfx::kGLImplementationNone)
510 return new CompositorGL(widget, size); 511 return new CompositorGL(widget, size);
511 return NULL;
512 } 512 }
513 513
514 } // namespace ui 514 } // namespace ui
OLDNEW
« no previous file with comments | « ui/gfx/compositor/compositor_gl.h ('k') | ui/gfx/compositor/compositor_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698