20 return "GL_INVALID_ENUM";
21 case GL_INVALID_VALUE:
22 return "GL_INVALID_VALUE";
23 case GL_INVALID_OPERATION:
24 return "GL_INVALID_OPERATION";
25 case GL_INVALID_FRAMEBUFFER_OPERATION:
26 return "GL_INVALID_FRAMEBUFFER_OPERATION";
27 case GL_FRAMEBUFFER_COMPLETE:
28 return "GL_FRAMEBUFFER_COMPLETE";
29 case GL_OUT_OF_MEMORY:
30 return "GL_OUT_OF_MEMORY";
37 return [resolver](
const char* function_name) ->
void* {
38 auto resolved = resolver(function_name);
44 auto function = std::string{function_name};
45 if (
function.find(
"KHR",
function.size() - 3) != std::string::npos) {
46 auto truncated =
function.substr(0u,
function.size() - 3);
47 return resolver(truncated.c_str());
49 if (
function.find(
"EXT",
function.size() - 3) != std::string::npos) {
50 auto truncated =
function.substr(0u,
function.size() - 3);
51 return resolver(truncated.c_str());
64 auto error_fn =
reinterpret_cast<PFNGLGETERRORPROC
>(resolver(
"glGetError"));
71 #define IMPELLER_PROC(proc_ivar) \
72 if (auto fn_ptr = resolver(proc_ivar.name)) { \
73 proc_ivar.function = \
74 reinterpret_cast<decltype(proc_ivar.function)>(fn_ptr); \
75 proc_ivar.error_fn = error_fn; \
77 VALIDATION_LOG << "Could not resolve " << proc_ivar.name; \
85 #define IMPELLER_PROC(proc_ivar) \
86 if (auto fn_ptr = resolver(proc_ivar.name)) { \
87 proc_ivar.function = \
88 reinterpret_cast<decltype(proc_ivar.function)>(fn_ptr); \
89 proc_ivar.error_fn = error_fn; \
96 description_ = std::make_unique<DescriptionGLES>(*
this);
98 if (!description_->IsValid()) {
102 if (!description_->HasDebugExtension()) {
103 PushDebugGroupKHR.Reset();
104 PopDebugGroupKHR.Reset();
105 ObjectLabelKHR.Reset();
107 GetIntegerv(GL_MAX_LABEL_LENGTH_KHR, &debug_label_max_length_);
110 if (!description_->HasExtension(
"GL_EXT_discard_framebuffer")) {
111 DiscardFramebufferEXT.Reset();
114 capabilities_ = std::make_unique<CapabilitiesGLES>(*
this);
126 const fml::Mapping& mapping)
const {
127 const GLchar* sources[] = {
128 reinterpret_cast<const GLchar*
>(mapping.GetMapping())};
129 const GLint lengths[] = {
static_cast<GLint
>(mapping.GetSize())};
130 ShaderSource(shader, 1u, sources, lengths);
134 return description_.get();
138 return capabilities_.get();
143 case GL_FRAMEBUFFER_COMPLETE:
144 return "GL_FRAMEBUFFER_COMPLETE";
145 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
146 return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
147 #if GL_ES_VERSION_2_0
148 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
149 return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
151 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
152 return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
153 case GL_FRAMEBUFFER_UNSUPPORTED:
154 return "GL_FRAMEBUFFER_UNSUPPORTED";
155 case GL_INVALID_ENUM:
156 return "GL_INVALID_ENUM";
159 return "Unknown FBO Error Status";
164 case GL_RENDERBUFFER:
165 return "GL_RENDERBUFFER";
172 return "Unknown Type";
177 GLint param = GL_NONE;
178 gl.GetFramebufferAttachmentParameteriv(
181 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
185 if (param != GL_NONE) {
187 gl.GetFramebufferAttachmentParameteriv(
190 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
193 std::stringstream stream;
198 return "No Attachment";
202 GLint framebuffer = GL_NONE;
203 GetIntegerv(GL_FRAMEBUFFER_BINDING, &framebuffer);
204 if (IsFramebuffer(framebuffer) == GL_FALSE) {
205 return "No framebuffer or the default window framebuffer is bound.";
208 GLenum status = CheckFramebufferStatus(framebuffer);
209 std::stringstream stream;
211 << ((framebuffer == GL_NONE) ?
"(Default)"
212 : std::to_string(framebuffer))
215 stream <<
"Framebuffer is complete." << std::endl;
217 stream <<
"Framebuffer is incomplete." << std::endl;
219 stream <<
"Description: " << std::endl;
220 stream <<
"Color Attachment: "
223 stream <<
"Color Attachment: "
226 stream <<
"Color Attachment: "
233 GLint framebuffer = GL_NONE;
234 GetIntegerv(GL_FRAMEBUFFER_BINDING, &framebuffer);
235 if (IsFramebuffer(framebuffer) == GL_FALSE) {
239 GLenum status = CheckFramebufferStatus(framebuffer);
240 return status == GL_FRAMEBUFFER_COMPLETE;
248 return GL_BUFFER_KHR;
250 return GL_PROGRAM_KHR;
252 return GL_SHADER_KHR;
254 return GL_RENDERBUFFER;
256 return GL_FRAMEBUFFER;
266 return gl.IsTexture(name);
268 return gl.IsBuffer(name);
270 return gl.IsProgram(name);
272 return gl.IsShader(name);
274 return gl.IsRenderbuffer(name);
276 return gl.IsFramebuffer(name);
283 const std::string& label)
const {
284 if (debug_label_max_length_ <= 0) {
287 if (!ObjectLabelKHR.IsAvailable()) {
294 const auto label_length =
295 std::min<GLsizei>(debug_label_max_length_ - 1, label.size());
296 if (!identifier.has_value()) {
299 ObjectLabelKHR(identifier.value(),
308 if (debug_label_max_length_ <= 0) {
312 const auto label_length =
313 std::min<GLsizei>(debug_label_max_length_ - 1, label.size());
314 PushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION_KHR,
315 static_cast<GLuint
>(
id.
id),
322 if (debug_label_max_length_ <= 0) {
330 GetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
335 length = std::min<GLint>(length, 1024);
337 if (!allocation.
Truncate(length,
false)) {
340 GetProgramInfoLog(program,
343 reinterpret_cast<GLchar*
>(allocation.
GetBuffer())
348 return std::string{
reinterpret_cast<const char*
>(allocation.
GetBuffer()),
349 static_cast<size_t>(length)};