Flutter Impeller
proc_table_gles.h
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 #ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_PROC_TABLE_GLES_H_
6 #define FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_PROC_TABLE_GLES_H_
7 
8 #include <functional>
9 #include <string>
10 
11 #include "flutter/fml/logging.h"
12 #include "flutter/fml/mapping.h"
16 
17 /// Enable to allow GLES to push/pop labels for usage in GPU traces
18 #define IP_ENABLE_GLES_LABELING false
19 
20 namespace impeller {
21 
22 const char* GLErrorToString(GLenum value);
23 bool GLErrorIsFatal(GLenum value);
24 
26  const PFNGLGETERRORPROC error_fn;
27 
28  // TODO(135922) Change to string_view.
29  const char* name;
30 
31  AutoErrorCheck(PFNGLGETERRORPROC error, const char* name)
32  : error_fn(error), name(name) {}
33 
35  if (error_fn) {
36  auto error = error_fn();
37  if (error == GL_NO_ERROR) {
38  return;
39  }
40  if (GLErrorIsFatal(error)) {
41  FML_LOG(FATAL) << "Fatal GL Error " << GLErrorToString(error) << "("
42  << error << ")" << " encountered on call to " << name;
43  } else {
44  FML_LOG(ERROR) << "GL Error " << GLErrorToString(error) << "(" << error
45  << ")" << " encountered on call to " << name;
46  }
47  }
48  }
49 };
50 
51 template <class Type>
52 void BuildGLArgumentsStream(std::stringstream& stream, Type arg) {
53  stream << arg;
54 }
55 
56 constexpr void BuildGLArgumentsStream(std::stringstream& stream) {}
57 
58 template <class Type, class... Rest>
59 void BuildGLArgumentsStream(std::stringstream& stream,
60  Type arg,
61  Rest... other_args) {
62  BuildGLArgumentsStream(stream, arg);
63  stream << ", ";
64  BuildGLArgumentsStream(stream, other_args...);
65 }
66 
67 template <class... Type>
68 [[nodiscard]] std::string BuildGLArguments(Type... args) {
69  std::stringstream stream;
70  stream << "(";
71  BuildGLArgumentsStream(stream, args...);
72  stream << ")";
73  return stream.str();
74 }
75 
76 template <class T>
77 struct GLProc {
78  using GLFunctionType = T;
79 
80  //----------------------------------------------------------------------------
81  /// The name of the GL function.
82  ///
83  // TODO(135922) Change to string_view.
84  const char* name = nullptr;
85 
86  //----------------------------------------------------------------------------
87  /// The pointer to the GL function.
88  ///
89  GLFunctionType* function = nullptr;
90 
91  //----------------------------------------------------------------------------
92  /// An optional error function. If present, all calls will be followed by an
93  /// error check.
94  ///
95  PFNGLGETERRORPROC error_fn = nullptr;
96 
97  //----------------------------------------------------------------------------
98  /// Whether the OpenGL call and its arguments should be logged.
99  ///
100  /// Only works in IMPELLER_DEBUG and for environments where traditional
101  /// tracing is hard. Expect log spam and only use during development.
102  ///
103  bool log_calls = false;
104 
105  //----------------------------------------------------------------------------
106  /// @brief Call the GL function with the appropriate parameters. Lookup
107  /// the documentation for the GL function being called to
108  /// understand the arguments and return types. The arguments
109  /// types must match and will be type checked.
110  ///
111  template <class... Args>
112  auto operator()(Args&&... args) const {
113 #if defined(IMPELLER_DEBUG) && !defined(NDEBUG)
114  AutoErrorCheck error(error_fn, name);
115  // We check for the existence of extensions, and reset the function pointer
116  // but it's still called unconditionally below, and will segfault. This
117  // validation log will at least give us a hint as to what's going on.
118  FML_CHECK(IsAvailable()) << "GL function " << name << " is not available. "
119  << "This is likely due to a missing extension.";
120  if (log_calls) {
121  FML_LOG(IMPORTANT) << name
122  << BuildGLArguments(std::forward<Args>(args)...);
123  }
124 #endif // defined(IMPELLER_DEBUG) && !defined(NDEBUG)
125  return function(std::forward<Args>(args)...);
126  }
127 
128  constexpr bool IsAvailable() const { return function != nullptr; }
129 
130  void Reset() {
131  function = nullptr;
132  error_fn = nullptr;
133  }
134 };
135 
136 #define FOR_EACH_IMPELLER_PROC(PROC) \
137  PROC(ActiveTexture); \
138  PROC(AttachShader); \
139  PROC(BindAttribLocation); \
140  PROC(BindBuffer); \
141  PROC(BindFramebuffer); \
142  PROC(BindRenderbuffer); \
143  PROC(BindTexture); \
144  PROC(BindVertexArray); \
145  PROC(BlendEquationSeparate); \
146  PROC(BlendFuncSeparate); \
147  PROC(BufferData); \
148  PROC(BufferSubData); \
149  PROC(CheckFramebufferStatus); \
150  PROC(Clear); \
151  PROC(ClearColor); \
152  PROC(ClearStencil); \
153  PROC(ColorMask); \
154  PROC(CompileShader); \
155  PROC(CreateProgram); \
156  PROC(CreateShader); \
157  PROC(CullFace); \
158  PROC(DeleteBuffers); \
159  PROC(DeleteFramebuffers); \
160  PROC(DeleteProgram); \
161  PROC(DeleteRenderbuffers); \
162  PROC(DeleteShader); \
163  PROC(DeleteTextures); \
164  PROC(DeleteVertexArrays); \
165  PROC(DepthFunc); \
166  PROC(DepthMask); \
167  PROC(DetachShader); \
168  PROC(Disable); \
169  PROC(DisableVertexAttribArray); \
170  PROC(DrawArrays); \
171  PROC(DrawElements); \
172  PROC(Enable); \
173  PROC(EnableVertexAttribArray); \
174  PROC(Finish); \
175  PROC(Flush); \
176  PROC(FramebufferRenderbuffer); \
177  PROC(FramebufferTexture2D); \
178  PROC(FrontFace); \
179  PROC(GenBuffers); \
180  PROC(GenerateMipmap); \
181  PROC(GenFramebuffers); \
182  PROC(GenRenderbuffers); \
183  PROC(GenTextures); \
184  PROC(GenVertexArrays); \
185  PROC(GetActiveUniform); \
186  PROC(GetBooleanv); \
187  PROC(GetFloatv); \
188  PROC(GetFramebufferAttachmentParameteriv); \
189  PROC(GetIntegerv); \
190  PROC(GetProgramInfoLog); \
191  PROC(GetProgramiv); \
192  PROC(GetShaderInfoLog); \
193  PROC(GetShaderiv); \
194  PROC(GetString); \
195  PROC(GetStringi); \
196  PROC(GetUniformLocation); \
197  PROC(IsBuffer); \
198  PROC(IsFramebuffer); \
199  PROC(IsProgram); \
200  PROC(IsRenderbuffer); \
201  PROC(IsShader); \
202  PROC(IsTexture); \
203  PROC(LinkProgram); \
204  PROC(PixelStorei); \
205  PROC(RenderbufferStorage); \
206  PROC(Scissor); \
207  PROC(ShaderBinary); \
208  PROC(ShaderSource); \
209  PROC(StencilFuncSeparate); \
210  PROC(StencilMaskSeparate); \
211  PROC(StencilOpSeparate); \
212  PROC(TexImage2D); \
213  PROC(TexSubImage2D); \
214  PROC(TexParameteri); \
215  PROC(TexParameterfv); \
216  PROC(Uniform1fv); \
217  PROC(Uniform1i); \
218  PROC(Uniform2fv); \
219  PROC(Uniform3fv); \
220  PROC(Uniform4fv); \
221  PROC(UniformMatrix4fv); \
222  PROC(UseProgram); \
223  PROC(VertexAttribPointer); \
224  PROC(Viewport); \
225  PROC(GetShaderSource); \
226  PROC(ReadPixels);
227 
228 // Calls specific to OpenGLES.
229 void(glClearDepthf)(GLfloat depth);
230 void(glDepthRangef)(GLfloat n, GLfloat f);
231 
232 #define FOR_EACH_IMPELLER_ES_ONLY_PROC(PROC) \
233  PROC(ClearDepthf); \
234  PROC(DepthRangef);
235 
236 // Calls specific to desktop GL.
237 void(glClearDepth)(GLdouble depth);
238 void(glDepthRange)(GLdouble n, GLdouble f);
239 
240 #define FOR_EACH_IMPELLER_DESKTOP_ONLY_PROC(PROC) \
241  PROC(ClearDepth); \
242  PROC(DepthRange);
243 
244 #define FOR_EACH_IMPELLER_GLES3_PROC(PROC) \
245  PROC(FenceSync); \
246  PROC(DeleteSync); \
247  PROC(GetActiveUniformBlockiv); \
248  PROC(GetActiveUniformBlockName); \
249  PROC(GetUniformBlockIndex); \
250  PROC(UniformBlockBinding); \
251  PROC(BindBufferRange); \
252  PROC(WaitSync); \
253  PROC(RenderbufferStorageMultisample) \
254  PROC(BlitFramebuffer);
255 
256 #define FOR_EACH_IMPELLER_EXT_PROC(PROC) \
257  PROC(DebugMessageControlKHR); \
258  PROC(DiscardFramebufferEXT); \
259  PROC(FramebufferTexture2DMultisampleEXT); \
260  PROC(PushDebugGroupKHR); \
261  PROC(PopDebugGroupKHR); \
262  PROC(ObjectLabelKHR); \
263  PROC(RenderbufferStorageMultisampleEXT); \
264  PROC(GenQueriesEXT); \
265  PROC(DeleteQueriesEXT); \
266  PROC(GetQueryObjectui64vEXT); \
267  PROC(BeginQueryEXT); \
268  PROC(EndQueryEXT); \
269  PROC(GetQueryObjectuivEXT); \
270  PROC(BlitFramebufferANGLE);
271 
272 enum class DebugResourceType {
273  kTexture,
274  kBuffer,
275  kProgram,
276  kShader,
278  kFrameBuffer,
279  kFence,
280 };
281 
283  public:
284  using Resolver = std::function<void*(const char* function_name)>;
285  explicit ProcTableGLES(Resolver resolver);
286  ProcTableGLES(ProcTableGLES&& other) = default;
287 
289 
290 #define IMPELLER_PROC(name) \
291  GLProc<decltype(gl##name)> name = {"gl" #name, nullptr};
292 
298 
299 #undef IMPELLER_PROC
300 
301  bool IsValid() const;
302 
303  /// @brief Set the source for the attached [shader].
304  ///
305  /// Optionally, [defines] may contain a string value that will be
306  /// append to the shader source after the version marker. This can be used to
307  /// support static specialization. For example, setting "#define Foo 1".
308  void ShaderSourceMapping(GLuint shader,
309  const fml::Mapping& mapping,
310  const std::vector<Scalar>& defines = {}) const;
311 
312  const DescriptionGLES* GetDescription() const;
313 
314  const std::shared_ptr<const CapabilitiesGLES>& GetCapabilities() const;
315 
316  std::string DescribeCurrentFramebuffer() const;
317 
318  std::string GetProgramInfoLogString(GLuint program) const;
319 
320  bool IsCurrentFramebufferComplete() const;
321 
322  bool SupportsDebugLabels() const;
323 
325  GLint name,
326  std::string_view label) const;
327 
328  void PushDebugGroup(const std::string& string) const;
329 
330  void PopDebugGroup() const;
331 
332  // Visible For testing.
333  std::optional<std::string> ComputeShaderWithDefines(
334  const fml::Mapping& mapping,
335  const std::vector<Scalar>& defines) const;
336 
337  private:
338  bool is_valid_ = false;
339  std::unique_ptr<DescriptionGLES> description_;
340  std::shared_ptr<const CapabilitiesGLES> capabilities_;
341  GLint debug_label_max_length_ = 0;
342 
343  ProcTableGLES(const ProcTableGLES&) = delete;
344 
345  ProcTableGLES& operator=(const ProcTableGLES&) = delete;
346 };
347 
348 } // namespace impeller
349 
350 #endif // FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_PROC_TABLE_GLES_H_
GLenum type
FOR_EACH_IMPELLER_ES_ONLY_PROC(IMPELLER_PROC)
ProcTableGLES(ProcTableGLES &&other)=default
std::optional< std::string > ComputeShaderWithDefines(const fml::Mapping &mapping, const std::vector< Scalar > &defines) const
bool SetDebugLabel(DebugResourceType type, GLint name, std::string_view label) const
FOR_EACH_IMPELLER_GLES3_PROC(IMPELLER_PROC)
std::function< void *(const char *function_name)> Resolver
void ShaderSourceMapping(GLuint shader, const fml::Mapping &mapping, const std::vector< Scalar > &defines={}) const
Set the source for the attached [shader].
FOR_EACH_IMPELLER_DESKTOP_ONLY_PROC(IMPELLER_PROC)
std::string GetProgramInfoLogString(GLuint program) const
bool SupportsDebugLabels() const
std::string DescribeCurrentFramebuffer() const
const std::shared_ptr< const CapabilitiesGLES > & GetCapabilities() const
bool IsCurrentFramebufferComplete() const
ProcTableGLES(Resolver resolver)
FOR_EACH_IMPELLER_PROC(IMPELLER_PROC)
FOR_EACH_IMPELLER_EXT_PROC(IMPELLER_PROC)
void PushDebugGroup(const std::string &string) const
const DescriptionGLES * GetDescription() const
int32_t value
void() glClearDepth(GLdouble depth)
bool GLErrorIsFatal(GLenum value)
void() glDepthRangef(GLfloat n, GLfloat f)
const char * GLErrorToString(GLenum value)
void BuildGLArgumentsStream(std::stringstream &stream, Type arg)
void() glDepthRange(GLdouble n, GLdouble f)
void() glClearDepthf(GLfloat depth)
std::string BuildGLArguments(Type... args)
#define IMPELLER_PROC(name)
AutoErrorCheck(PFNGLGETERRORPROC error, const char *name)
const PFNGLGETERRORPROC error_fn
auto operator()(Args &&... args) const
Call the GL function with the appropriate parameters. Lookup the documentation for the GL function be...
const char * name
constexpr bool IsAvailable() const
PFNGLGETERRORPROC error_fn