Flutter Engine
ios_render_target_gl.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter 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 #import "flutter/shell/platform/darwin/ios/ios_render_target_gl.h"
6 
7 #include <UIKit/UIKit.h>
8 
9 #include "flutter/fml/trace_event.h"
10 #include "third_party/skia/include/gpu/GrContextOptions.h"
11 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
12 
13 namespace flutter {
14 
17  : layer_(std::move(layer)), context_(context) {
18  FML_DCHECK(layer_ != nullptr);
19  FML_DCHECK(context_ != nullptr);
20 
21  if (@available(iOS 9.0, *)) {
22  [layer_ setPresentsWithTransaction:YES];
23  }
24  auto context_switch = GLContextSwitch(std::make_unique<IOSSwitchableGLContext>(context_.get()));
25  bool context_current = context_switch.GetResult();
26 
27  FML_DCHECK(context_current);
28  FML_DCHECK(glGetError() == GL_NO_ERROR);
29 
30  // Generate the framebuffer
31 
32  glGenFramebuffers(1, &framebuffer_);
33  FML_DCHECK(glGetError() == GL_NO_ERROR);
34  FML_DCHECK(framebuffer_ != GL_NONE);
35 
36  glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
37  FML_DCHECK(glGetError() == GL_NO_ERROR);
38 
39  // Setup color attachment
40 
41  glGenRenderbuffers(1, &colorbuffer_);
42  FML_DCHECK(colorbuffer_ != GL_NONE);
43 
44  glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer_);
45  FML_DCHECK(glGetError() == GL_NO_ERROR);
46 
47  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer_);
48  FML_DCHECK(glGetError() == GL_NO_ERROR);
49 
50  NSString* drawableColorFormat = kEAGLColorFormatRGBA8;
51  layer_.get().drawableProperties = @{
52  kEAGLDrawablePropertyColorFormat : drawableColorFormat,
53  kEAGLDrawablePropertyRetainedBacking : @(NO),
54  };
55 
56  valid_ = true;
57 }
58 
60  auto context_switch = GLContextSwitch(std::make_unique<IOSSwitchableGLContext>(context_.get()));
61  FML_DCHECK(glGetError() == GL_NO_ERROR);
62 
63  // Deletes on GL_NONEs are ignored
64  glDeleteFramebuffers(1, &framebuffer_);
65  glDeleteRenderbuffers(1, &colorbuffer_);
66 
67  FML_DCHECK(glGetError() == GL_NO_ERROR);
68 }
69 
70 // |IOSRenderTarget|
72  return valid_;
73 }
74 
75 // |IOSRenderTarget|
77  return framebuffer_;
78 }
79 
80 // |IOSRenderTarget|
82  const GLenum discards[] = {
83  GL_DEPTH_ATTACHMENT,
84  GL_STENCIL_ATTACHMENT,
85  };
86 
87  glDiscardFramebufferEXT(GL_FRAMEBUFFER, sizeof(discards) / sizeof(GLenum), discards);
88 
89  glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer_);
90  auto current_context = [EAGLContext currentContext];
91  FML_DCHECK(current_context != nullptr);
92  return [current_context presentRenderbuffer:GL_RENDERBUFFER];
93 }
94 
95 // |IOSRenderTarget|
97  const CGSize layer_size = [layer_.get() bounds].size;
98  const CGFloat contents_scale = layer_.get().contentsScale;
99  const GLint size_width = layer_size.width * contents_scale;
100  const GLint size_height = layer_size.height * contents_scale;
101 
102  if (size_width == storage_size_width_ && size_height == storage_size_height_) {
103  // Nothing to do since the storage size is already consistent with the layer.
104  return true;
105  }
106  TRACE_EVENT_INSTANT0("flutter", "IOSRenderTargetGL::UpdateStorageSizeIfNecessary");
107  FML_DLOG(INFO) << "Updating render buffer storage size.";
108 
109  FML_DCHECK(glGetError() == GL_NO_ERROR);
110 
111  auto context_switch = GLContextSwitch(std::make_unique<IOSSwitchableGLContext>(context_.get()));
112  if (!context_switch.GetResult()) {
113  return false;
114  }
115 
116  FML_DCHECK(glGetError() == GL_NO_ERROR);
117 
118  glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
119 
120  glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer_);
121  FML_DCHECK(glGetError() == GL_NO_ERROR);
122 
123  auto current_context = [EAGLContext currentContext];
124  if (![current_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer_.get()]) {
125  return false;
126  }
127 
128  // Fetch the dimensions of the color buffer whose backing was just updated.
129  glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &storage_size_width_);
130  FML_DCHECK(glGetError() == GL_NO_ERROR);
131 
132  glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &storage_size_height_);
133  FML_DCHECK(glGetError() == GL_NO_ERROR);
134 
135  FML_DCHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
136 
137  return true;
138 }
139 
140 } // namespace flutter
#define FML_DCHECK(condition)
Definition: logging.h:86
FML_THREAD_LOCAL fml::ThreadLocalUniquePtr< int > current_context
#define TRACE_EVENT_INSTANT0(category_group, name)
Definition: trace_event.h:104
Definition: ref_ptr.h:252
IOSRenderTargetGL(fml::scoped_nsobject< CAEAGLLayer > layer, fml::scoped_nsobject< EAGLContext > context_)
#define FML_DLOG(severity)
Definition: logging.h:85