blob: 9dedad039b84b6d2251cdbf4ad0846ebc2f6d871 [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gl/init/create_gr_gl_interface.h"
#include "base/no_destructor.h"
#include "base/trace_event/trace_event.h"
#include "base/traits_bag.h"
#include "build/build_config.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_display.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_utils.h"
#include "ui/gl/gl_version_info.h"
#include "ui/gl/progress_reporter.h"
#if BUILDFLAG(IS_MAC)
#include "base/mac/mac_util.h"
#endif
namespace gl::init {
// This code emulates GL fences (GL_APPLE_sync or GL_ARB_sync) via
// EGL_KHR_fence_sync extension. It's used to provide Skia ways of
// synchronization on platforms that does not have GL fences but support EGL
namespace {
struct EGLFenceData {
EGLSync sync;
EGLDisplay display;
};
GLsync glFenceSyncEmulateEGL(GLenum condition, GLbitfield flags) {
DCHECK(condition == GL_SYNC_GPU_COMMANDS_COMPLETE);
DCHECK(flags == 0);
// Prefer EGL_ANGLE_global_fence_sync as it guarantees synchronization with
// past submissions from all contexts, rather than the current context.
gl::GLContext* context = gl::GLContext::GetCurrent();
gl::GLDisplayEGL* display = context ? context->GetGLDisplayEGL() : nullptr;
const EGLenum syncType =
display && display->ext->b_EGL_ANGLE_global_fence_sync
? EGL_SYNC_GLOBAL_FENCE_ANGLE
: EGL_SYNC_FENCE_KHR;
init::EGLFenceData* data = new EGLFenceData;
data->display = eglGetCurrentDisplay();
data->sync = eglCreateSyncKHR(data->display, syncType, nullptr);
return reinterpret_cast<GLsync>(data);
}
void glDeleteSyncEmulateEGL(GLsync sync) {
EGLFenceData* data = reinterpret_cast<EGLFenceData*>(sync);
eglDestroySyncKHR(data->display, data->sync);
delete data;
}
GLenum glClientWaitSyncEmulateEGL(GLsync sync,
GLbitfield flags,
GLuint64 timeout) {
init::EGLFenceData* data = reinterpret_cast<init::EGLFenceData*>(sync);
EGLint egl_flags = 0;
if (flags & GL_SYNC_FLUSH_COMMANDS_BIT) {
egl_flags |= EGL_SYNC_FLUSH_COMMANDS_BIT;
}
EGLint result =
eglClientWaitSyncKHR(data->display, data->sync, egl_flags, timeout);
switch (result) {
case EGL_CONDITION_SATISFIED:
return GL_CONDITION_SATISFIED;
case EGL_TIMEOUT_EXPIRED:
return GL_TIMEOUT_EXPIRED;
case EGL_FALSE:
return GL_WAIT_FAILED;
}
NOTREACHED();
return 0;
}
void glWaitSyncEmulateEGL(GLsync sync, GLbitfield flags, GLuint64 timeout) {
init::EGLFenceData* data = reinterpret_cast<init::EGLFenceData*>(sync);
DCHECK(timeout == GL_TIMEOUT_IGNORED);
DCHECK(flags == 0);
if (!GetDefaultDisplayEGL()->ext->b_EGL_KHR_wait_sync) {
eglClientWaitSyncKHR(data->display, data->sync, 0, EGL_FOREVER_KHR);
return;
}
EGLint result = eglWaitSyncKHR(data->display, data->sync, 0);
DCHECK(result);
}
GLboolean glIsSyncEmulateEGL(GLsync sync) {
NOTREACHED();
return true;
}
} // namespace
namespace {
template <typename R, typename... Args>
GrGLFunction<R GR_GL_FUNCTION_TYPE(Args...)> bind_with_api(
R (gl::GLApi::*func)(Args...),
gl::GLApi* api) {
return [func, api](Args... args) { return (api->*func)(args...); };
}
struct FlushHelper {
FlushHelper() {
TRACE_EVENT0("gpu",
"CreateGrGLInterface - bind_with_flush_on_mac - beforefunc");
glFlush();
}
~FlushHelper() {
TRACE_EVENT0("gpu",
"CreateGrGLInterface - bind_with_flush_on_mac - afterfunc");
glFlush();
}
};
template <bool droppable,
bool slow,
bool need_flush,
typename R,
typename... Args>
GrGLFunction<R GR_GL_FUNCTION_TYPE(Args...)> bind_impl(
R(GL_BINDING_CALL* func)(Args...),
gl::ProgressReporter* progress_reporter) {
// Don't wrap missing functions.
if (!func)
return nullptr;
constexpr bool need_wrap = droppable || slow || need_flush;
if constexpr (need_wrap) {
return [func, progress_reporter](Args... args) -> R {
if constexpr (droppable) {
if (HasInitializedNullDrawGLBindings())
return R();
}
std::optional<gl::ScopedProgressReporter> scoped_reporter;
// Not using constexpr if here to avoid unused progress_reporter warning.
if (slow && progress_reporter)
scoped_reporter.emplace(progress_reporter);
std::optional<FlushHelper> flush_helper;
if constexpr (need_flush)
flush_helper.emplace();
return func(args...);
};
} else {
return func;
}
}
// Call can be dropped for tests that setup null draw gl bindings.
struct Droppable {};
// Call needs to be wrapped with ProgressReporter.
struct Slow {};
// Call needs to be wrapped with glFlush call, used on MacOS.
struct NeedFlush {};
#if BUILDFLAG(IS_MAC)
using SlowOnMac = Slow;
using NeedFlushOnMac = NeedFlush;
#else
using SlowOnMac = void;
using NeedFlushOnMac = void;
#endif
template <typename... Traits>
struct BindWithTraits {
template <typename R, typename... Args>
static GrGLFunction<R GR_GL_FUNCTION_TYPE(Args...)> bind(
R(GL_BINDING_CALL* func)(Args...),
gl::ProgressReporter* progress_reporter,
bool is_angle) {
constexpr bool droppable =
base::trait_helpers::HasTrait<Droppable, Traits...>();
constexpr bool slow = base::trait_helpers::HasTrait<Slow, Traits...>();
constexpr bool need_flush =
base::trait_helpers::HasTrait<NeedFlush, Traits...>();
#if BUILDFLAG(IS_MAC)
// If running on Apple silicon, regardless of the architecture, don't
// perform this workaround. See https://crbug.com/1131312.
if (need_flush && base::mac::GetCPUType() == base::mac::CPUType::kIntel &&
!is_angle) {
return bind_impl<droppable, slow, /*need_flush=*/true>(func,
progress_reporter);
} else {
return bind_impl<droppable, slow, /*need_flush=*/false>(
func, progress_reporter);
}
#else
return bind_impl<droppable, slow, need_flush>(func, progress_reporter);
#endif
}
};
const GLubyte* GetStringHook(const char* gl_version_string,
const char* glsl_version_string,
GLenum name) {
switch (name) {
case GL_VERSION:
return reinterpret_cast<const GLubyte*>(gl_version_string);
case GL_SHADING_LANGUAGE_VERSION:
return reinterpret_cast<const GLubyte*>(glsl_version_string);
default:
return glGetString(name);
}
}
const char* kBlocklistExtensions[] = {
"GL_APPLE_framebuffer_multisample",
"GL_ARB_ES3_1_compatibility",
"GL_ARB_draw_indirect",
"GL_ARB_invalidate_subdata",
"GL_ARB_multi_draw_indirect",
"GL_ARB_sample_shading",
"GL_ARB_texture_barrier",
"GL_CHROMIUM_framebuffer_mixed_samples",
"GL_EXT_direct_state_access",
"GL_EXT_multi_draw_indirect",
"GL_EXT_raster_multisample",
"GL_NV_bindless_texture",
"GL_NV_framebuffer_mixed_samples",
"GL_NV_texture_barrier",
"GL_OES_sample_shading",
"GL_EXT_draw_instanced",
};
} // anonymous namespace
sk_sp<GrGLInterface> CreateGrGLInterface(
const gl::GLVersionInfo& version_info,
gl::ProgressReporter* progress_reporter) {
gl::ProcsGL* gl = &gl::g_current_gl_driver->fn;
gl::GLApi* api = gl::g_current_gl_context;
GrGLStandard standard =
version_info.is_es ? kGLES_GrGLStandard : kGL_GrGLStandard;
// Depending on the advertised version and extensions, skia checks for
// existence of entrypoints. However some of those we don't yet handle in
// gl_bindings, so we need to fake the version to the maximum fully supported
// by the bindings (GL 4.1 or ES 3.0), and blocklist extensions that skia
// handles but bindings don't.
// TODO(piman): add bindings for missing entrypoints.
GrGLFunction<GrGLGetStringFn> get_string;
const bool apply_version_override =
version_info.IsAtLeastGL(4, 2) || version_info.IsAtLeastGLES(3, 1);
if (apply_version_override || version_info.IsVersionSubstituted()) {
GLVersionInfo::VersionStrings version;
if (version_info.IsVersionSubstituted()) {
version = version_info.GetFakeVersionStrings(version_info.major_version,
version_info.minor_version);
} else if (version_info.is_es) {
version = version_info.GetFakeVersionStrings(3, 0);
} else {
version = version_info.GetFakeVersionStrings(4, 1);
}
get_string = [version](GLenum name) {
return GetStringHook(version.gl_version, version.glsl_version, name);
};
} else {
get_string = bind_with_api(&gl::GLApi::glGetStringFn, api);
}
auto get_stringi = bind_with_api(&gl::GLApi::glGetStringiFn, api);
auto get_integerv = bind_with_api(&gl::GLApi::glGetIntegervFn, api);
GrGLExtensions extensions;
if (!extensions.init(standard, get_string, get_stringi, get_integerv)) {
LOG(ERROR) << "Failed to initialize extensions";
return nullptr;
}
for (const char* extension : kBlocklistExtensions)
extensions.remove(extension);
#define BIND_EXTENSION(skia_name, chrome_name, ...) \
functions->f##skia_name = BindWithTraits<__VA_ARGS__>::bind( \
gl->gl##chrome_name##Fn, progress_reporter, version_info.is_angle)
#define BIND(fname, ...) BIND_EXTENSION(fname, fname, __VA_ARGS__)
GrGLInterface* gl_interface = new GrGLInterface();
GrGLInterface::Functions* functions = &gl_interface->fFunctions;
BIND(ActiveTexture);
BIND(AttachShader);
BIND(BindAttribLocation);
BIND(BindBuffer);
BIND(BindFragDataLocation);
BIND_EXTENSION(BindUniformLocation, BindUniformLocationCHROMIUM);
BIND(BeginQuery);
BIND(BindSampler);
BIND(BindTexture, SlowOnMac);
BIND_EXTENSION(BlendBarrier, BlendBarrierKHR);
BIND(BlendColor);
BIND(BlendEquation);
BIND(BlendFunc);
BIND(BufferData);
BIND(BufferSubData);
BIND(Clear, Droppable, SlowOnMac, NeedFlushOnMac);
BIND(ClearColor);
BIND(ClearStencil);
BIND(ClearTexImage);
BIND(ClearTexSubImage);
BIND(ColorMask);
BIND(CompileShader, Slow);
BIND(CompressedTexImage2D, Slow, NeedFlushOnMac);
BIND(CompressedTexSubImage2D, Slow);
BIND(CopyBufferSubData);
BIND(CopyTexSubImage2D, Slow);
BIND(CreateProgram);
BIND(CreateShader);
BIND(CullFace);
BIND_EXTENSION(DeleteBuffers, DeleteBuffersARB, Slow);
BIND(DeleteProgram, Slow);
BIND(DeleteQueries);
BIND(DeleteSamplers);
BIND(DeleteShader, Slow);
BIND(DeleteTextures, Slow, NeedFlushOnMac);
BIND(DepthMask);
BIND(Disable);
BIND(DisableVertexAttribArray);
BIND_EXTENSION(DiscardFramebuffer, DiscardFramebufferEXT);
BIND(DrawArrays, Droppable, SlowOnMac);
BIND(DrawBuffer);
BIND_EXTENSION(DrawBuffers, DrawBuffersARB);
BIND(DrawElements, Droppable, SlowOnMac);
BIND_EXTENSION(DrawArraysInstanced, DrawArraysInstancedANGLE, Droppable,
SlowOnMac);
BIND_EXTENSION(DrawArraysInstancedBaseInstance,
DrawArraysInstancedBaseInstanceANGLE, Droppable, SlowOnMac);
BIND_EXTENSION(MultiDrawArraysInstancedBaseInstance,
MultiDrawArraysInstancedBaseInstanceANGLE, Droppable,
SlowOnMac);
BIND_EXTENSION(DrawElementsInstanced, DrawElementsInstancedANGLE, Droppable,
SlowOnMac);
BIND_EXTENSION(DrawElementsInstancedBaseVertexBaseInstance,
DrawElementsInstancedBaseVertexBaseInstanceANGLE, Droppable,
SlowOnMac);
BIND_EXTENSION(MultiDrawElementsInstancedBaseVertexBaseInstance,
MultiDrawElementsInstancedBaseVertexBaseInstanceANGLE,
Droppable, SlowOnMac);
// GL 4.0 or GL_ARB_draw_indirect or ES 3.1
BIND(DrawArraysIndirect, Droppable, SlowOnMac);
BIND(DrawElementsIndirect, Droppable, SlowOnMac);
BIND(DrawRangeElements, Droppable, SlowOnMac);
BIND(Enable);
BIND(EnableVertexAttribArray);
BIND(EndQuery);
BIND(Finish, Slow);
BIND(Flush, Slow);
BIND(FrontFace);
BIND_EXTENSION(GenBuffers, GenBuffersARB);
BIND(GetBufferParameteriv);
BIND(GetError);
BIND(GetFloatv);
BIND(GetIntegerv);
BIND(GetMultisamplefv);
BIND(GetQueryObjectiv);
BIND(GetQueryObjectuiv);
BIND(GetQueryObjecti64v);
BIND(GetQueryObjectui64v);
BIND(QueryCounter);
BIND(GetQueryiv);
BIND(GetProgramBinary);
BIND(GetProgramInfoLog);
BIND(GetProgramiv);
BIND(GetShaderInfoLog);
BIND(GetShaderiv);
functions->fGetString = get_string;
BIND(GetStringi);
BIND(GetShaderPrecisionFormat);
BIND(GetTexLevelParameteriv);
BIND(GenQueries);
BIND(GenSamplers);
BIND(GenTextures);
BIND(GetUniformLocation);
BIND(IsTexture);
BIND(LineWidth);
BIND(LinkProgram, Slow);
BIND(MapBuffer);
// GL 4.3 or GL_ARB_multi_draw_indirect or ES+GL_EXT_multi_draw_indirect
// BIND(MultiDrawArraysIndirect);
// BIND(MultiDrawElementsIndirect);
BIND(PatchParameteri);
BIND(PixelStorei);
BIND(PolygonMode);
// TODO(vasilyt): Figure out why BIND(fProgramBinary) doesn't fit in
// GrFunction
functions->fProgramBinary = gl->glProgramBinaryFn;
BIND(ProgramParameteri);
// GL_EXT_raster_multisample
// BIND_EXTENSION(RasterSamples , RasterSamplesEXT);
BIND(ReadBuffer);
BIND(ReadPixels);
BIND(SamplerParameterf);
BIND(SamplerParameteri);
BIND(SamplerParameteriv);
BIND(Scissor);
BIND(ShaderSource);
BIND(StencilFunc);
BIND(StencilFuncSeparate);
BIND(StencilMask);
BIND(StencilMaskSeparate);
BIND(StencilOp);
BIND(StencilOpSeparate);
BIND(TexBuffer);
BIND(TexBufferRange);
BIND(TexImage2D, Slow, NeedFlushOnMac);
BIND(TexParameterf);
BIND(TexParameterfv);
BIND(TexParameteri);
BIND(TexParameteriv);
BIND_EXTENSION(TexStorage2D, TexStorage2DEXT, Slow, NeedFlushOnMac);
BIND(TexSubImage2D, Slow, NeedFlushOnMac);
// GL 4.5 or GL_ARB_texture_barrier or GL_NV_texture_barrier
// BIND(TextureBarrier);
// BIND_EXTENSION(TextureBarrier , TextureBarrierNV);
BIND(Uniform1f);
BIND(Uniform1i);
BIND(Uniform1fv);
BIND(Uniform1iv);
BIND(Uniform2f);
BIND(Uniform2i);
BIND(Uniform2fv);
BIND(Uniform2iv);
BIND(Uniform3f);
BIND(Uniform3i);
BIND(Uniform3fv);
BIND(Uniform3iv);
BIND(Uniform4f);
BIND(Uniform4i);
BIND(Uniform4fv);
BIND(Uniform4iv);
BIND(UniformMatrix2fv);
BIND(UniformMatrix3fv);
BIND(UniformMatrix4fv);
BIND(UnmapBuffer);
BIND(UseProgram);
BIND(VertexAttrib1f);
BIND(VertexAttrib2fv);
BIND(VertexAttrib3fv);
BIND(VertexAttrib4fv);
BIND_EXTENSION(VertexAttribDivisor, VertexAttribDivisorANGLE);
BIND(VertexAttribIPointer);
BIND(VertexAttribPointer);
BIND(Viewport);
BIND(BindFragDataLocationIndexed);
BIND_EXTENSION(BindVertexArray, BindVertexArrayOES);
BIND_EXTENSION(GenVertexArrays, GenVertexArraysOES);
BIND_EXTENSION(DeleteVertexArrays, DeleteVertexArraysOES);
BIND(MapBufferRange);
BIND(FlushMappedBufferRange);
BIND_EXTENSION(GenerateMipmap, GenerateMipmapEXT);
BIND_EXTENSION(GenFramebuffers, GenFramebuffersEXT);
BIND_EXTENSION(GetFramebufferAttachmentParameteriv,
GetFramebufferAttachmentParameterivEXT);
BIND_EXTENSION(GetRenderbufferParameteriv, GetRenderbufferParameterivEXT);
BIND_EXTENSION(BindFramebuffer, BindFramebufferEXT, Slow, NeedFlushOnMac);
BIND_EXTENSION(FramebufferTexture2D, FramebufferTexture2DEXT);
BIND_EXTENSION(CheckFramebufferStatus, CheckFramebufferStatusEXT);
BIND_EXTENSION(DeleteFramebuffers, DeleteFramebuffersEXT, Slow,
NeedFlushOnMac);
BIND_EXTENSION(RenderbufferStorage, RenderbufferStorageEXT, NeedFlushOnMac);
BIND_EXTENSION(GenRenderbuffers, GenRenderbuffersEXT);
BIND_EXTENSION(DeleteRenderbuffers, DeleteRenderbuffersEXT, NeedFlushOnMac);
BIND_EXTENSION(FramebufferRenderbuffer, FramebufferRenderbufferEXT);
BIND_EXTENSION(BindRenderbuffer, BindRenderbufferEXT);
BIND(RenderbufferStorageMultisample, NeedFlushOnMac);
BIND_EXTENSION(FramebufferTexture2DMultisample,
FramebufferTexture2DMultisampleEXT);
BIND_EXTENSION(RenderbufferStorageMultisampleES2EXT,
RenderbufferStorageMultisampleEXT, NeedFlushOnMac);
BIND(BlitFramebuffer, NeedFlushOnMac);
BIND_EXTENSION(InsertEventMarker, InsertEventMarkerEXT);
BIND_EXTENSION(PushGroupMarker, PushGroupMarkerEXT);
BIND_EXTENSION(PopGroupMarker, PopGroupMarkerEXT);
// GL 4.3 or GL_ARB_invalidate_subdata
// BIND(InvalidateBufferData);
// BIND(InvalidateBufferSubData);
// BIND(InvalidateTexImage);
// BIND(InvalidateTexSubImage);
BIND(InvalidateFramebuffer);
BIND(InvalidateSubFramebuffer);
// GL_NV_bindless_texture
// BIND_EXTENSION(GetTextureHandle , GetTextureHandleNV);
// BIND_EXTENSION(GetTextureSamplerHandle , GetTextureSamplerHandleNV);
// BIND_EXTENSION(MakeTextureHandleResident , MakeTextureHandleResidentNV);
// BIND_EXTENSION(MakeTextureHandleNonResident ,
// MakeTextureHandleNonResidentNV); BIND_EXTENSION(GetImageHandle ,
// GetImageHandleNV); BIND_EXTENSION(MakeImageHandleResident ,
// MakeImageHandleResidentNV); BIND_EXTENSION(MakeImageHandleNonResident ,
// MakeImageHandleNonResidentNV); BIND_EXTENSION(IsTextureHandleResident ,
// IsTextureHandleResidentNV); BIND_EXTENSION(IsImageHandleResident ,
// IsImageHandleResidentNV); BIND_EXTENSION(UniformHandleui64 ,
// UniformHandleui64NV); BIND_EXTENSION(UniformHandleui64v ,
// UniformHandleui64vNV); BIND_EXTENSION(ProgramUniformHandleui64 ,
// ProgramUniformHandleui64NV); BIND_EXTENSION(ProgramUniformHandleui64v ,
// ProgramUniformHandleui64vNV);
// GL_EXT_direct_state_access
// BIND_EXTENSION(TextureParameteri , TextureParameteriEXT);
// BIND_EXTENSION(TextureParameteriv , TextureParameterivEXT);
// BIND_EXTENSION(TextureParameterf , TextureParameterfEXT);
// BIND_EXTENSION(TextureParameterfv , TextureParameterfvEXT);
// BIND_EXTENSION(TextureImage1D , TextureImage1DEXT);
// BIND_EXTENSION(TextureImage2D , TextureImage2DEXT);
// BIND_EXTENSION(TextureSubImage1D , TextureSubImage1DEXT);
// BIND_EXTENSION(TextureSubImage2D , TextureSubImage2DEXT);
// BIND_EXTENSION(CopyTextureImage1D , CopyTextureImage1DEXT);
// BIND_EXTENSION(CopyTextureImage2D , CopyTextureImage2DEXT);
// BIND_EXTENSION(CopyTextureSubImage1D , CopyTextureSubImage1DEXT);
// BIND_EXTENSION(CopyTextureSubImage2D , CopyTextureSubImage2DEXT);
// BIND_EXTENSION(GetNamedBufferParameteriv , GetNamedBufferParameterivEXT);
// BIND_EXTENSION(GetNamedBufferPointerv , GetNamedBufferPointervEXT);
// BIND_EXTENSION(GetNamedBufferSubData , GetNamedBufferSubDataEXT);
// BIND_EXTENSION(GetTextureImage , GetTextureImageEXT);
// BIND_EXTENSION(GetTextureParameterfv , GetTextureParameterfvEXT);
// BIND_EXTENSION(GetTextureParameteriv , GetTextureParameterivEXT);
// BIND_EXTENSION(GetTextureLevelParameterfv , GetTextureLevelParameterfvEXT);
// BIND_EXTENSION(GetTextureLevelParameteriv , GetTextureLevelParameterivEXT);
// BIND_EXTENSION(MapNamedBuffer , MapNamedBufferEXT);
// BIND_EXTENSION(NamedBufferData , NamedBufferDataEXT);
// BIND_EXTENSION(NamedBufferSubData , NamedBufferSubDataEXT);
// BIND_EXTENSION(ProgramUniform1f , ProgramUniform1fEXT);
// BIND_EXTENSION(ProgramUniform2f , ProgramUniform2fEXT);
// BIND_EXTENSION(ProgramUniform3f , ProgramUniform3fEXT);
// BIND_EXTENSION(ProgramUniform4f , ProgramUniform4fEXT);
// BIND_EXTENSION(ProgramUniform1i , ProgramUniform1iEXT);
// BIND_EXTENSION(ProgramUniform2i , ProgramUniform2iEXT);
// BIND_EXTENSION(ProgramUniform3i , ProgramUniform3iEXT);
// BIND_EXTENSION(ProgramUniform4i , ProgramUniform4iEXT);
// BIND_EXTENSION(ProgramUniform1fv , ProgramUniform1fvEXT);
// BIND_EXTENSION(ProgramUniform2fv , ProgramUniform2fvEXT);
// BIND_EXTENSION(ProgramUniform3fv , ProgramUniform3fvEXT);
// BIND_EXTENSION(ProgramUniform4fv , ProgramUniform4fvEXT);
// BIND_EXTENSION(ProgramUniform1iv , ProgramUniform1ivEXT);
// BIND_EXTENSION(ProgramUniform2iv , ProgramUniform2ivEXT);
// BIND_EXTENSION(ProgramUniform3iv , ProgramUniform3ivEXT);
// BIND_EXTENSION(ProgramUniform4iv , ProgramUniform4ivEXT);
// BIND_EXTENSION(ProgramUniformMatrix2fv , ProgramUniformMatrix2fvEXT);
// BIND_EXTENSION(ProgramUniformMatrix3fv , ProgramUniformMatrix3fvEXT);
// BIND_EXTENSION(ProgramUniformMatrix4fv , ProgramUniformMatrix4fvEXT);
// BIND_EXTENSION(UnmapNamedBuffer , UnmapNamedBufferEXT);
// BIND_EXTENSION(TextureImage3D , TextureImage3DEXT);
// BIND_EXTENSION(TextureSubImage3D , TextureSubImage3DEXT);
// BIND_EXTENSION(CopyTextureSubImage3D , CopyTextureSubImage3DEXT);
// BIND_EXTENSION(CompressedTextureImage3D , CompressedTextureImage3DEXT);
// BIND_EXTENSION(CompressedTextureImage2D , CompressedTextureImage2DEXT);
// BIND_EXTENSION(CompressedTextureImage1D , CompressedTextureImage1DEXT);
// BIND_EXTENSION(CompressedTextureSubImage3D,
// CompressedTextureSubImage3DEXT);
// BIND_EXTENSION(CompressedTextureSubImage2D,
// CompressedTextureSubImage2DEXT);
// BIND_EXTENSION(CompressedTextureSubImage1D,
// CompressedTextureSubImage1DEXT);
// BIND_EXTENSION(GetCompressedTextureImage, GetCompressedTextureImageEXT);
// BIND_EXTENSION(ProgramUniformMatrix2x3fv, ProgramUniformMatrix2x3fvEXT);
// BIND_EXTENSION(ProgramUniformMatrix3x2fv, ProgramUniformMatrix3x2fvEXT);
// BIND_EXTENSION(ProgramUniformMatrix2x4fv, ProgramUniformMatrix2x4fvEXT);
// BIND_EXTENSION(ProgramUniformMatrix4x2fv, ProgramUniformMatrix4x2fvEXT);
// BIND_EXTENSION(ProgramUniformMatrix3x4fv, ProgramUniformMatrix3x4fvEXT);
// BIND_EXTENSION(ProgramUniformMatrix4x3fv, ProgramUniformMatrix4x3fvEXT);
// BIND_EXTENSION(NamedRenderbufferStorage, NamedRenderbufferStorageEXT);
// BIND_EXTENSION(GetNamedRenderbufferParameteriv,
// GetNamedRenderbufferParameterivEXT);
// BIND_EXTENSION(NamedRenderbufferStorageMultisample,
// NamedRenderbufferStorageMultisampleEXT);
// BIND_EXTENSION(CheckNamedFramebufferStatus,
// CheckNamedFramebufferStatusEXT);
// BIND_EXTENSION(NamedFramebufferTexture1D, NamedFramebufferTexture1DEXT);
// BIND_EXTENSION(NamedFramebufferTexture2D, NamedFramebufferTexture2DEXT);
// BIND_EXTENSION(NamedFramebufferTexture3D, NamedFramebufferTexture3DEXT);
// BIND_EXTENSION(NamedFramebufferRenderbuffer,
// NamedFramebufferRenderbufferEXT);
// BIND_EXTENSION(GetNamedFramebufferAttachmentParameteriv,
// GetNamedFramebufferAttachmentParameterivEXT);
// BIND_EXTENSION(GenerateTextureMipmap, GenerateTextureMipmapEXT);
// BIND_EXTENSION(FramebufferDrawBuffer, FramebufferDrawBufferEXT);
// BIND_EXTENSION(FramebufferDrawBuffers, FramebufferDrawBuffersEXT);
// BIND_EXTENSION(FramebufferReadBuffer, FramebufferReadBufferEXT);
// BIND_EXTENSION(GetFramebufferParameteriv, GetFramebufferParameterivEXT);
// BIND_EXTENSION(NamedCopyBufferSubData, NamedCopyBufferSubDataEXT);
// BIND_EXTENSION(VertexArrayVertexOffset, VertexArrayVertexOffsetEXT);
// BIND_EXTENSION(VertexArrayColorOffset, VertexArrayColorOffsetEXT);
// BIND_EXTENSION(VertexArrayEdgeFlagOffset, VertexArrayEdgeFlagOffsetEXT);
// BIND_EXTENSION(VertexArrayIndexOffset, VertexArrayIndexOffsetEXT);
// BIND_EXTENSION(VertexArrayNormalOffset, VertexArrayNormalOffsetEXT);
// BIND_EXTENSION(VertexArrayTexCoordOffset, VertexArrayTexCoordOffsetEXT);
// BIND_EXTENSION(VertexArrayMultiTexCoordOffset,
// VertexArrayMultiTexCoordOffsetEXT);
// BIND_EXTENSION(VertexArrayFogCoordOffset, VertexArrayFogCoordOffsetEXT);
// BIND_EXTENSION(VertexArraySecondaryColorOffset,
// VertexArraySecondaryColorOffsetEXT);
// BIND_EXTENSION(VertexArrayVertexAttribOffset,
// VertexArrayVertexAttribOffsetEXT);
// BIND_EXTENSION(VertexArrayVertexAttribIOffset,
// VertexArrayVertexAttribIOffsetEXT);
// BIND_EXTENSION(EnableVertexArray, EnableVertexArrayEXT);
// BIND_EXTENSION(DisableVertexArray, DisableVertexArrayEXT);
// BIND_EXTENSION(EnableVertexArrayAttrib, EnableVertexArrayAttribEXT);
// BIND_EXTENSION(DisableVertexArrayAttrib, DisableVertexArrayAttribEXT);
// BIND_EXTENSION(GetVertexArrayIntegerv, GetVertexArrayIntegervEXT);
// BIND_EXTENSION(GetVertexArrayPointerv, GetVertexArrayPointervEXT);
// BIND_EXTENSION(GetVertexArrayIntegeri_v, GetVertexArrayIntegeri_vEXT);
// BIND_EXTENSION(GetVertexArrayPointeri_v, GetVertexArrayPointeri_vEXT);
// BIND_EXTENSION(MapNamedBufferRange, MapNamedBufferRangeEXT);
// BIND_EXTENSION(FlushMappedNamedBufferRange,
// FlushMappedNamedBufferRangeEXT);
// BIND_EXTENSION(TextureBuffer, TextureBufferEXT);
// Some drivers report GL_KHR_debug but do not provide functions. Validate and
// remove reported extension from the list if necessary
// See https://crbug.com/1008125
if (gl->glDebugMessageControlFn && gl->glDebugMessageInsertFn &&
gl->glDebugMessageCallbackFn && gl->glGetDebugMessageLogFn &&
gl->glPushDebugGroupFn && gl->glPopDebugGroupFn && gl->glObjectLabelFn) {
BIND(DebugMessageControl);
BIND(DebugMessageInsert);
BIND(DebugMessageCallback);
BIND(GetDebugMessageLog);
BIND(PushDebugGroup);
BIND(PopDebugGroup);
BIND(ObjectLabel);
} else {
extensions.remove("GL_KHR_debug");
}
// GL_EXT_window_rectangles
BIND_EXTENSION(WindowRectangles, WindowRectanglesEXT);
// GL_QCOM_tiled_rendering
BIND_EXTENSION(StartTiling, StartTilingQCOM);
BIND_EXTENSION(EndTiling, EndTilingQCOM);
// EGL_KHR_image / EGL_KHR_image_base
// functions->fCreateImage = nullptr;
// functions->fDestroyImage = nullptr;
BIND(FenceSync);
BIND(IsSync);
BIND(ClientWaitSync);
BIND(WaitSync);
BIND(DeleteSync);
if (!gl->glFenceSyncFn) {
// NOTE: Skia uses the same function pointers without APPLE suffix
#if !defined(USE_EGL)
if (extensions.has("GL_APPLE_sync")) {
BIND_EXTENSION(FenceSync, FenceSyncAPPLE);
BIND_EXTENSION(IsSync, IsSyncAPPLE);
BIND_EXTENSION(ClientWaitSync, ClientWaitSyncAPPLE);
BIND_EXTENSION(WaitSync, WaitSyncAPPLE);
BIND_EXTENSION(DeleteSync, DeleteSyncAPPLE);
}
#else
if (GetDefaultDisplayEGL()->ext->b_EGL_KHR_fence_sync) {
// Emulate APPLE_sync via egl
extensions.add("GL_APPLE_sync");
functions->fFenceSync = glFenceSyncEmulateEGL;
functions->fIsSync = glIsSyncEmulateEGL;
functions->fClientWaitSync = glClientWaitSyncEmulateEGL;
functions->fWaitSync = glWaitSyncEmulateEGL;
functions->fDeleteSync = glDeleteSyncEmulateEGL;
}
#endif // USE_EGL
}
// Skia can fall back to GL_NV_fence if GLsync objects are not available.
BIND_EXTENSION(DeleteFences, DeleteFencesNV);
BIND_EXTENSION(FinishFence, FinishFenceNV);
BIND_EXTENSION(GenFences, GenFencesNV);
BIND_EXTENSION(SetFence, SetFenceNV);
BIND_EXTENSION(TestFence, TestFenceNV);
BIND(GetInternalformativ);
#undef BIND
#undef BIND_EXTENSION
gl_interface->fStandard = standard;
gl_interface->fExtensions.swap(&extensions);
sk_sp<GrGLInterface> returned(gl_interface);
return returned;
}
} // namespace gl::init