blob: b167a595a034a8024fda7fb29ec6961edc313690 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// 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/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "build/build_config.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_version_info.h"
#include "ui/gl/progress_reporter.h"
namespace gl {
namespace 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);
init::EGLFenceData* data = new EGLFenceData;
data->display = eglGetCurrentDisplay();
data->sync = eglCreateSyncKHR(data->display, EGL_SYNC_FENCE_KHR, 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 (!g_driver_egl.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;
}
#if defined(OS_MACOSX)
std::map<GLuint, base::TimeTicks>& GetProgramCreateTimesMap() {
static base::NoDestructor<std::map<GLuint, base::TimeTicks>> instance;
return *instance.get();
}
#endif
} // namespace
namespace {
template <typename R, typename... Args>
GrGLFunction<R GR_GL_FUNCTION_TYPE(Args...)> bind(R (gl::GLApi::*func)(Args...),
gl::GLApi* api) {
return [func, api](Args... args) { return (api->*func)(args...); };
}
template <typename R, typename... Args>
GrGLFunction<R GR_GL_FUNCTION_TYPE(Args...)> bind_slow(
R(GL_BINDING_CALL* func)(Args...),
gl::ProgressReporter* progress_reporter) {
if (!progress_reporter)
return func;
return [func, progress_reporter](Args... args) {
gl::ScopedProgressReporter scoped_reporter(progress_reporter);
return func(args...);
};
}
template <bool droppable_call, typename R, typename... Args>
GrGLFunction<R GR_GL_FUNCTION_TYPE(Args...)> maybe_drop_call(
R(GL_BINDING_CALL* func)(Args...)) {
// One branch is optimized away because droppable_call is set at compile time.
if (droppable_call) {
return [func](Args... args) {
if (!HasInitializedNullDrawGLBindings())
func(args...);
};
} else {
return func;
}
}
template <bool droppable_call = false, typename R, typename... Args>
GrGLFunction<R GR_GL_FUNCTION_TYPE(Args...)> bind_slow_on_mac(
R(GL_BINDING_CALL* func)(Args...),
gl::ProgressReporter* progress_reporter) {
#if defined(OS_MACOSX)
if (!progress_reporter) {
return maybe_drop_call<droppable_call>(func);
}
return [func, progress_reporter](Args... args) {
gl::ScopedProgressReporter scoped_reporter(progress_reporter);
// Conditional may be optimized out because droppable_call is set at compile
// time.
if (!droppable_call || !HasInitializedNullDrawGLBindings())
return func(args...);
};
#endif
return maybe_drop_call<droppable_call>(func);
}
template <bool droppable_call = false, typename R, typename... Args>
GrGLFunction<R GR_GL_FUNCTION_TYPE(Args...)> bind_with_flush_on_mac(
R(GL_BINDING_CALL* func)(Args...)) {
#if defined(OS_MACOSX)
return [func](Args... args) {
// Conditional may be optimized out because droppable_call is set at compile
// time.
if (!droppable_call || !HasInitializedNullDrawGLBindings()) {
glFlush();
func(args...);
glFlush();
}
};
#else
return maybe_drop_call<droppable_call>(func);
#endif
}
template <bool droppable_call = false, typename R, typename... Args>
GrGLFunction<R GR_GL_FUNCTION_TYPE(Args...)> bind_slow_with_flush_on_mac(
R(GL_BINDING_CALL* func)(Args...),
gl::ProgressReporter* progress_reporter) {
if (!progress_reporter) {
return bind_with_flush_on_mac<droppable_call>(func);
}
return [func, progress_reporter](Args... args) {
gl::ScopedProgressReporter scoped_reporter(progress_reporter);
return bind_with_flush_on_mac<droppable_call>(func)(args...);
};
}
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* kBlacklistExtensions[] = {
"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_EXT_direct_state_access",
"GL_EXT_multi_draw_indirect",
"GL_EXT_raster_multisample",
"GL_NV_bindless_texture",
"GL_NV_texture_barrier",
"GL_OES_sample_shading",
};
} // anonymous namespace
sk_sp<GrGLInterface> CreateGrGLInterface(
const gl::GLVersionInfo& version_info,
bool use_version_es2,
gl::ProgressReporter* progress_reporter) {
// Can't fake ES with desktop GL.
use_version_es2 &= version_info.is_es;
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 blacklist extensions that skia
// handles but bindings don't.
// TODO(piman): add bindings for missing entrypoints.
GrGLFunction<GrGLGetStringFn> get_string;
const bool apply_version_override = use_version_es2 ||
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) {
if (use_version_es2)
version = version_info.GetFakeVersionStrings(2, 0);
else
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(&gl::GLApi::glGetStringFn, api);
}
auto get_stringi = bind(&gl::GLApi::glGetStringiFn, api);
auto get_integerv = bind(&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 : kBlacklistExtensions)
extensions.remove(extension);
GrGLInterface* interface = new GrGLInterface();
GrGLInterface::Functions* functions = &interface->fFunctions;
functions->fActiveTexture = gl->glActiveTextureFn;
functions->fAttachShader = gl->glAttachShaderFn;
functions->fBindAttribLocation = gl->glBindAttribLocationFn;
functions->fBindBuffer = gl->glBindBufferFn;
functions->fBindFragDataLocation = gl->glBindFragDataLocationFn;
functions->fBindUniformLocation = gl->glBindUniformLocationCHROMIUMFn;
functions->fBeginQuery = gl->glBeginQueryFn;
functions->fBindSampler = gl->glBindSamplerFn;
functions->fBindTexture =
bind_slow_on_mac(gl->glBindTextureFn, progress_reporter);
functions->fBlendBarrier = gl->glBlendBarrierKHRFn;
functions->fBlendColor = gl->glBlendColorFn;
functions->fBlendEquation = gl->glBlendEquationFn;
functions->fBlendFunc = gl->glBlendFuncFn;
functions->fBufferData = gl->glBufferDataFn;
functions->fBufferSubData = gl->glBufferSubDataFn;
functions->fClear =
bind_slow_with_flush_on_mac<true>(gl->glClearFn, progress_reporter);
functions->fClearColor = gl->glClearColorFn;
functions->fClearStencil = gl->glClearStencilFn;
functions->fClearTexImage = gl->glClearTexImageFn;
functions->fClearTexSubImage = gl->glClearTexSubImageFn;
functions->fColorMask = gl->glColorMaskFn;
functions->fCompileShader =
bind_slow(gl->glCompileShaderFn, progress_reporter);
functions->fCompressedTexImage2D = bind_slow_with_flush_on_mac(
gl->glCompressedTexImage2DFn, progress_reporter);
functions->fCompressedTexSubImage2D =
bind_slow(gl->glCompressedTexSubImage2DFn, progress_reporter);
functions->fCopyTexSubImage2D =
bind_slow(gl->glCopyTexSubImage2DFn, progress_reporter);
#if defined(OS_MACOSX)
functions->fCreateProgram = [func = gl->glCreateProgramFn]() {
auto& program_create_times = GetProgramCreateTimesMap();
GLuint program = func();
program_create_times[program] = base::TimeTicks::Now();
return program;
};
#else
functions->fCreateProgram = gl->glCreateProgramFn;
#endif
functions->fCreateShader = gl->glCreateShaderFn;
functions->fCullFace = gl->glCullFaceFn;
functions->fDeleteBuffers =
bind_slow(gl->glDeleteBuffersARBFn, progress_reporter);
#if defined(OS_MACOSX)
functions->fDeleteProgram = [func = gl->glDeleteProgramFn](GLuint program) {
auto& program_create_times = GetProgramCreateTimesMap();
program_create_times.erase(program);
func(program);
};
#else
functions->fDeleteProgram =
bind_slow(gl->glDeleteProgramFn, progress_reporter);
#endif
functions->fDeleteQueries = gl->glDeleteQueriesFn;
functions->fDeleteSamplers = gl->glDeleteSamplersFn;
functions->fDeleteShader = bind_slow(gl->glDeleteShaderFn, progress_reporter);
functions->fDeleteTextures =
bind_slow_with_flush_on_mac(gl->glDeleteTexturesFn, progress_reporter);
functions->fDepthMask = gl->glDepthMaskFn;
functions->fDisable = gl->glDisableFn;
functions->fDisableVertexAttribArray = gl->glDisableVertexAttribArrayFn;
functions->fDiscardFramebuffer = gl->glDiscardFramebufferEXTFn;
functions->fDrawArrays =
bind_slow_on_mac<true>(gl->glDrawArraysFn, progress_reporter);
functions->fDrawBuffer = gl->glDrawBufferFn;
functions->fDrawBuffers = gl->glDrawBuffersARBFn;
functions->fDrawElements =
bind_slow_on_mac<true>(gl->glDrawElementsFn, progress_reporter);
functions->fDrawArraysInstanced = bind_slow_on_mac<true>(
gl->glDrawArraysInstancedANGLEFn, progress_reporter);
functions->fDrawElementsInstanced = bind_slow_on_mac<true>(
gl->glDrawElementsInstancedANGLEFn, progress_reporter);
// GL 4.0 or GL_ARB_draw_indirect or ES 3.1
functions->fDrawArraysIndirect =
bind_slow_on_mac<true>(gl->glDrawArraysIndirectFn, progress_reporter);
functions->fDrawElementsIndirect =
bind_slow_on_mac<true>(gl->glDrawElementsIndirectFn, progress_reporter);
functions->fDrawRangeElements =
bind_slow_on_mac<true>(gl->glDrawRangeElementsFn, progress_reporter);
functions->fEnable = gl->glEnableFn;
functions->fEnableVertexAttribArray = gl->glEnableVertexAttribArrayFn;
functions->fEndQuery = gl->glEndQueryFn;
functions->fFinish = bind_slow(gl->glFinishFn, progress_reporter);
functions->fFlush = bind_slow(gl->glFlushFn, progress_reporter);
functions->fFrontFace = gl->glFrontFaceFn;
functions->fGenBuffers = gl->glGenBuffersARBFn;
functions->fGetBufferParameteriv = gl->glGetBufferParameterivFn;
functions->fGetError = gl->glGetErrorFn;
functions->fGetIntegerv = gl->glGetIntegervFn;
functions->fGetMultisamplefv = gl->glGetMultisamplefvFn;
functions->fGetQueryObjectiv = gl->glGetQueryObjectivFn;
functions->fGetQueryObjectuiv = gl->glGetQueryObjectuivFn;
functions->fGetQueryObjecti64v = gl->glGetQueryObjecti64vFn;
functions->fGetQueryObjectui64v = gl->glGetQueryObjectui64vFn;
functions->fQueryCounter = gl->glQueryCounterFn;
functions->fGetQueryiv = gl->glGetQueryivFn;
functions->fGetProgramBinary = gl->glGetProgramBinaryFn;
functions->fGetProgramInfoLog = gl->glGetProgramInfoLogFn;
#if defined(OS_MACOSX)
functions->fGetProgramiv = [func = gl->glGetProgramivFn](
GLuint program, GLenum pname, GLint* params) {
func(program, pname, params);
if (pname == 0x8B82 /* GR_GL_LINK_STATUS */) {
auto& program_create_times = GetProgramCreateTimesMap();
auto found = program_create_times.find(program);
if (found != program_create_times.end()) {
base::TimeDelta elapsed = base::TimeTicks::Now() - found->second;
UMA_HISTOGRAM_TIMES("Gpu.GL.ProgramBuildTime", elapsed);
program_create_times.erase(found);
}
}
};
#else
functions->fGetProgramiv = gl->glGetProgramivFn;
#endif
functions->fGetShaderInfoLog = gl->glGetShaderInfoLogFn;
functions->fGetShaderiv = gl->glGetShaderivFn;
functions->fGetString = get_string;
functions->fGetStringi = gl->glGetStringiFn;
functions->fGetShaderPrecisionFormat = gl->glGetShaderPrecisionFormatFn;
functions->fGetTexLevelParameteriv = gl->glGetTexLevelParameterivFn;
functions->fGenQueries = gl->glGenQueriesFn;
functions->fGenSamplers = gl->glGenSamplersFn;
functions->fGenTextures = gl->glGenTexturesFn;
functions->fGetUniformLocation = gl->glGetUniformLocationFn;
functions->fIsTexture = gl->glIsTextureFn;
functions->fLineWidth = gl->glLineWidthFn;
functions->fLinkProgram = bind_slow(gl->glLinkProgramFn, progress_reporter);
functions->fMapBuffer = gl->glMapBufferFn;
// GL 4.3 or GL_ARB_multi_draw_indirect or ES+GL_EXT_multi_draw_indirect
// functions->fMultiDrawArraysIndirect = gl->glMultiDrawArraysIndirectFn;
// functions->fMultiDrawElementsIndirect = gl->glMultiDrawElementsIndirectFn;
functions->fPixelStorei = gl->glPixelStoreiFn;
functions->fPolygonMode = gl->glPolygonModeFn;
functions->fProgramBinary = gl->glProgramBinaryFn;
functions->fProgramParameteri = gl->glProgramParameteriFn;
// GL_EXT_raster_multisample
// functions->fRasterSamples = gl->glRasterSamplesEXTFn;
functions->fReadBuffer = gl->glReadBufferFn;
functions->fReadPixels = gl->glReadPixelsFn;
functions->fSamplerParameteri = gl->glSamplerParameteriFn;
functions->fSamplerParameteriv = gl->glSamplerParameterivFn;
functions->fScissor = gl->glScissorFn;
functions->fShaderSource = gl->glShaderSourceFn;
functions->fStencilFunc = gl->glStencilFuncFn;
functions->fStencilFuncSeparate = gl->glStencilFuncSeparateFn;
functions->fStencilMask = gl->glStencilMaskFn;
functions->fStencilMaskSeparate = gl->glStencilMaskSeparateFn;
functions->fStencilOp = gl->glStencilOpFn;
functions->fStencilOpSeparate = gl->glStencilOpSeparateFn;
functions->fTexBuffer = gl->glTexBufferFn;
functions->fTexBufferRange = gl->glTexBufferRangeFn;
functions->fTexImage2D =
bind_slow_with_flush_on_mac(gl->glTexImage2DFn, progress_reporter);
functions->fTexParameterf = gl->glTexParameterfFn;
functions->fTexParameterfv = gl->glTexParameterfvFn;
functions->fTexParameteri = gl->glTexParameteriFn;
functions->fTexParameteriv = gl->glTexParameterivFn;
functions->fTexStorage2D =
bind_slow_with_flush_on_mac(gl->glTexStorage2DEXTFn, progress_reporter);
functions->fTexSubImage2D =
bind_slow_with_flush_on_mac(gl->glTexSubImage2DFn, progress_reporter);
// GL 4.5 or GL_ARB_texture_barrier or GL_NV_texture_barrier
// functions->fTextureBarrier = gl->glTextureBarrierFn;
// functions->fTextureBarrier = gl->glTextureBarrierNVFn;
functions->fUniform1f = gl->glUniform1fFn;
functions->fUniform1i = gl->glUniform1iFn;
functions->fUniform1fv = gl->glUniform1fvFn;
functions->fUniform1iv = gl->glUniform1ivFn;
functions->fUniform2f = gl->glUniform2fFn;
functions->fUniform2i = gl->glUniform2iFn;
functions->fUniform2fv = gl->glUniform2fvFn;
functions->fUniform2iv = gl->glUniform2ivFn;
functions->fUniform3f = gl->glUniform3fFn;
functions->fUniform3i = gl->glUniform3iFn;
functions->fUniform3fv = gl->glUniform3fvFn;
functions->fUniform3iv = gl->glUniform3ivFn;
functions->fUniform4f = gl->glUniform4fFn;
functions->fUniform4i = gl->glUniform4iFn;
functions->fUniform4fv = gl->glUniform4fvFn;
functions->fUniform4iv = gl->glUniform4ivFn;
functions->fUniformMatrix2fv = gl->glUniformMatrix2fvFn;
functions->fUniformMatrix3fv = gl->glUniformMatrix3fvFn;
functions->fUniformMatrix4fv = gl->glUniformMatrix4fvFn;
functions->fUnmapBuffer = gl->glUnmapBufferFn;
functions->fUseProgram = gl->glUseProgramFn;
functions->fVertexAttrib1f = gl->glVertexAttrib1fFn;
functions->fVertexAttrib2fv = gl->glVertexAttrib2fvFn;
functions->fVertexAttrib3fv = gl->glVertexAttrib3fvFn;
functions->fVertexAttrib4fv = gl->glVertexAttrib4fvFn;
functions->fVertexAttribDivisor = gl->glVertexAttribDivisorANGLEFn;
functions->fVertexAttribIPointer = gl->glVertexAttribIPointerFn;
functions->fVertexAttribPointer = gl->glVertexAttribPointerFn;
functions->fViewport = gl->glViewportFn;
functions->fBindFragDataLocationIndexed = gl->glBindFragDataLocationIndexedFn;
functions->fBindVertexArray = gl->glBindVertexArrayOESFn;
functions->fGenVertexArrays = gl->glGenVertexArraysOESFn;
functions->fDeleteVertexArrays = gl->glDeleteVertexArraysOESFn;
functions->fMapBufferRange = gl->glMapBufferRangeFn;
functions->fFlushMappedBufferRange = gl->glFlushMappedBufferRangeFn;
functions->fGenerateMipmap = gl->glGenerateMipmapEXTFn;
functions->fGenFramebuffers = gl->glGenFramebuffersEXTFn;
functions->fGetFramebufferAttachmentParameteriv =
gl->glGetFramebufferAttachmentParameterivEXTFn;
functions->fGetRenderbufferParameteriv =
gl->glGetRenderbufferParameterivEXTFn;
functions->fBindFramebuffer =
bind_with_flush_on_mac(gl->glBindFramebufferEXTFn);
functions->fFramebufferTexture2D = gl->glFramebufferTexture2DEXTFn;
functions->fCheckFramebufferStatus = gl->glCheckFramebufferStatusEXTFn;
functions->fDeleteFramebuffers = bind_slow_with_flush_on_mac(
gl->glDeleteFramebuffersEXTFn, progress_reporter);
functions->fRenderbufferStorage =
bind_with_flush_on_mac(gl->glRenderbufferStorageEXTFn);
functions->fGenRenderbuffers = gl->glGenRenderbuffersEXTFn;
functions->fDeleteRenderbuffers =
bind_with_flush_on_mac(gl->glDeleteRenderbuffersEXTFn);
functions->fFramebufferRenderbuffer = gl->glFramebufferRenderbufferEXTFn;
functions->fBindRenderbuffer = gl->glBindRenderbufferEXTFn;
functions->fRenderbufferStorageMultisample =
bind_with_flush_on_mac(gl->glRenderbufferStorageMultisampleFn);
functions->fFramebufferTexture2DMultisample =
gl->glFramebufferTexture2DMultisampleEXTFn;
functions->fRenderbufferStorageMultisampleES2EXT =
bind_with_flush_on_mac(gl->glRenderbufferStorageMultisampleEXTFn);
functions->fBlitFramebuffer = bind_with_flush_on_mac(gl->glBlitFramebufferFn);
functions->fMatrixLoadf = gl->glMatrixLoadfEXTFn;
functions->fMatrixLoadIdentity = gl->glMatrixLoadIdentityEXTFn;
functions->fPathCommands = gl->glPathCommandsNVFn;
functions->fPathParameteri = gl->glPathParameteriNVFn;
functions->fPathParameterf = gl->glPathParameterfNVFn;
functions->fGenPaths = gl->glGenPathsNVFn;
functions->fDeletePaths = gl->glDeletePathsNVFn;
functions->fIsPath = gl->glIsPathNVFn;
functions->fPathStencilFunc = gl->glPathStencilFuncNVFn;
functions->fStencilFillPath = gl->glStencilFillPathNVFn;
functions->fStencilStrokePath = gl->glStencilStrokePathNVFn;
functions->fStencilFillPathInstanced = gl->glStencilFillPathInstancedNVFn;
functions->fStencilStrokePathInstanced = gl->glStencilStrokePathInstancedNVFn;
functions->fCoverFillPath = gl->glCoverFillPathNVFn;
functions->fCoverStrokePath = gl->glCoverStrokePathNVFn;
functions->fCoverFillPathInstanced = gl->glCoverFillPathInstancedNVFn;
functions->fCoverStrokePathInstanced = gl->glCoverStrokePathInstancedNVFn;
functions->fStencilThenCoverFillPath = gl->glStencilThenCoverFillPathNVFn;
functions->fStencilThenCoverStrokePath = gl->glStencilThenCoverStrokePathNVFn;
functions->fStencilThenCoverFillPathInstanced =
gl->glStencilThenCoverFillPathInstancedNVFn;
functions->fStencilThenCoverStrokePathInstanced =
gl->glStencilThenCoverStrokePathInstancedNVFn;
functions->fProgramPathFragmentInputGen =
gl->glProgramPathFragmentInputGenNVFn;
functions->fBindFragmentInputLocation =
gl->glBindFragmentInputLocationCHROMIUMFn;
functions->fCoverageModulation = gl->glCoverageModulationNVFn;
functions->fInsertEventMarker = gl->glInsertEventMarkerEXTFn;
functions->fPushGroupMarker = gl->glPushGroupMarkerEXTFn;
functions->fPopGroupMarker = gl->glPopGroupMarkerEXTFn;
// GL 4.3 or GL_ARB_invalidate_subdata
// functions->fInvalidateBufferData = gl->glInvalidateBufferDataFn;
// functions->fInvalidateBufferSubData = gl->glInvalidateBufferSubDataFn;
// functions->fInvalidateTexImage = gl->glInvalidateTexImageFn;
// functions->fInvalidateTexSubImage = gl->glInvalidateTexSubImageFn;
functions->fInvalidateFramebuffer = gl->glInvalidateFramebufferFn;
functions->fInvalidateSubFramebuffer = gl->glInvalidateSubFramebufferFn;
functions->fGetProgramResourceLocation = gl->glGetProgramResourceLocationFn;
// GL_NV_bindless_texture
// functions->fGetTextureHandle = gl->glGetTextureHandleNVFn;
// functions->fGetTextureSamplerHandle = gl->glGetTextureSamplerHandleNVFn;
// functions->fMakeTextureHandleResident =
// gl->glMakeTextureHandleResidentNVFn;
// functions->fMakeTextureHandleNonResident =
// gl->glMakeTextureHandleNonResidentNVFn;
// functions->fGetImageHandle = gl->glGetImageHandleNVFn;
// functions->fMakeImageHandleResident = gl->glMakeImageHandleResidentNVFn;
// functions->fMakeImageHandleNonResident =
// gl->glMakeImageHandleNonResidentNVFn;
// functions->fIsTextureHandleResident = gl->glIsTextureHandleResidentNVFn;
// functions->fIsImageHandleResident = gl->glIsImageHandleResidentNVFn;
// functions->fUniformHandleui64 = gl->glUniformHandleui64NVFn;
// functions->fUniformHandleui64v = gl->glUniformHandleui64vNVFn;
// functions->fProgramUniformHandleui64 = gl->glProgramUniformHandleui64NVFn;
// functions->fProgramUniformHandleui64v =
// gl->glProgramUniformHandleui64vNVFn;
// GL_EXT_direct_state_access
// functions->fTextureParameteri = gl->glTextureParameteriEXTFn;
// functions->fTextureParameteriv = gl->glTextureParameterivEXTFn;
// functions->fTextureParameterf = gl->glTextureParameterfEXTFn;
// functions->fTextureParameterfv = gl->glTextureParameterfvEXTFn;
// functions->fTextureImage1D = gl->glTextureImage1DEXTFn;
// functions->fTextureImage2D = gl->glTextureImage2DEXTFn;
// functions->fTextureSubImage1D = gl->glTextureSubImage1DEXTFn;
// functions->fTextureSubImage2D = gl->glTextureSubImage2DEXTFn;
// functions->fCopyTextureImage1D = gl->glCopyTextureImage1DEXTFn;
// functions->fCopyTextureImage2D = gl->glCopyTextureImage2DEXTFn;
// functions->fCopyTextureSubImage1D = gl->glCopyTextureSubImage1DEXTFn;
// functions->fCopyTextureSubImage2D = gl->glCopyTextureSubImage2DEXTFn;
// functions->fGetNamedBufferParameteriv =
// gl->glGetNamedBufferParameterivEXTFn;
// functions->fGetNamedBufferPointerv = gl->glGetNamedBufferPointervEXTFn;
// functions->fGetNamedBufferSubData = gl->glGetNamedBufferSubDataEXTFn;
// functions->fGetTextureImage = gl->glGetTextureImageEXTFn;
// functions->fGetTextureParameterfv = gl->glGetTextureParameterfvEXTFn;
// functions->fGetTextureParameteriv = gl->glGetTextureParameterivEXTFn;
// functions->fGetTextureLevelParameterfv =
// gl->glGetTextureLevelParameterfvEXTFn;
// functions->fGetTextureLevelParameteriv =
// gl->glGetTextureLevelParameterivEXTFn;
// functions->fMapNamedBuffer = gl->glMapNamedBufferEXTFn;
// functions->fNamedBufferData = gl->glNamedBufferDataEXTFn;
// functions->fNamedBufferSubData = gl->glNamedBufferSubDataEXTFn;
// functions->fProgramUniform1f = gl->glProgramUniform1fEXTFn;
// functions->fProgramUniform2f = gl->glProgramUniform2fEXTFn;
// functions->fProgramUniform3f = gl->glProgramUniform3fEXTFn;
// functions->fProgramUniform4f = gl->glProgramUniform4fEXTFn;
// functions->fProgramUniform1i = gl->glProgramUniform1iEXTFn;
// functions->fProgramUniform2i = gl->glProgramUniform2iEXTFn;
// functions->fProgramUniform3i = gl->glProgramUniform3iEXTFn;
// functions->fProgramUniform4i = gl->glProgramUniform4iEXTFn;
// functions->fProgramUniform1fv = gl->glProgramUniform1fvEXTFn;
// functions->fProgramUniform2fv = gl->glProgramUniform2fvEXTFn;
// functions->fProgramUniform3fv = gl->glProgramUniform3fvEXTFn;
// functions->fProgramUniform4fv = gl->glProgramUniform4fvEXTFn;
// functions->fProgramUniform1iv = gl->glProgramUniform1ivEXTFn;
// functions->fProgramUniform2iv = gl->glProgramUniform2ivEXTFn;
// functions->fProgramUniform3iv = gl->glProgramUniform3ivEXTFn;
// functions->fProgramUniform4iv = gl->glProgramUniform4ivEXTFn;
// functions->fProgramUniformMatrix2fv = gl->glProgramUniformMatrix2fvEXTFn;
// functions->fProgramUniformMatrix3fv = gl->glProgramUniformMatrix3fvEXTFn;
// functions->fProgramUniformMatrix4fv = gl->glProgramUniformMatrix4fvEXTFn;
// functions->fUnmapNamedBuffer = gl->glUnmapNamedBufferEXTFn;
// functions->fTextureImage3D = gl->glTextureImage3DEXTFn;
// functions->fTextureSubImage3D = gl->glTextureSubImage3DEXTFn;
// functions->fCopyTextureSubImage3D = gl->glCopyTextureSubImage3DEXTFn;
// functions->fCompressedTextureImage3D = gl->glCompressedTextureImage3DEXTFn;
// functions->fCompressedTextureImage2D = gl->glCompressedTextureImage2DEXTFn;
// functions->fCompressedTextureImage1D = gl->glCompressedTextureImage1DEXTFn;
// functions->fCompressedTextureSubImage3D =
// gl->glCompressedTextureSubImage3DEXTFn;
// functions->fCompressedTextureSubImage2D =
// gl->glCompressedTextureSubImage2DEXTFn;
// functions->fCompressedTextureSubImage1D =
// gl->glCompressedTextureSubImage1DEXTFn;
// functions->fGetCompressedTextureImage =
// gl->glGetCompressedTextureImageEXTFn;
// functions->fProgramUniformMatrix2x3fv =
// gl->glProgramUniformMatrix2x3fvEXTFn;
// functions->fProgramUniformMatrix3x2fv =
// gl->glProgramUniformMatrix3x2fvEXTFn;
// functions->fProgramUniformMatrix2x4fv =
// gl->glProgramUniformMatrix2x4fvEXTFn;
// functions->fProgramUniformMatrix4x2fv =
// gl->glProgramUniformMatrix4x2fvEXTFn;
// functions->fProgramUniformMatrix3x4fv =
// gl->glProgramUniformMatrix3x4fvEXTFn;
// functions->fProgramUniformMatrix4x3fv =
// gl->glProgramUniformMatrix4x3fvEXTFn;
// functions->fNamedRenderbufferStorage = gl->glNamedRenderbufferStorageEXTFn;
// functions->fGetNamedRenderbufferParameteriv =
// gl->glGetNamedRenderbufferParameterivEXTFn;
// functions->fNamedRenderbufferStorageMultisample =
// gl->glNamedRenderbufferStorageMultisampleEXTFn;
// functions->fCheckNamedFramebufferStatus =
// gl->glCheckNamedFramebufferStatusEXTFn;
// functions->fNamedFramebufferTexture1D =
// gl->glNamedFramebufferTexture1DEXTFn;
// functions->fNamedFramebufferTexture2D =
// gl->glNamedFramebufferTexture2DEXTFn;
// functions->fNamedFramebufferTexture3D =
// gl->glNamedFramebufferTexture3DEXTFn;
// functions->fNamedFramebufferRenderbuffer =
// gl->glNamedFramebufferRenderbufferEXTFn;
// functions->fGetNamedFramebufferAttachmentParameteriv =
// gl->glGetNamedFramebufferAttachmentParameterivEXTFn;
// functions->fGenerateTextureMipmap = gl->glGenerateTextureMipmapEXTFn;
// functions->fFramebufferDrawBuffer = gl->glFramebufferDrawBufferEXTFn;
// functions->fFramebufferDrawBuffers = gl->glFramebufferDrawBuffersEXTFn;
// functions->fFramebufferReadBuffer = gl->glFramebufferReadBufferEXTFn;
// functions->fGetFramebufferParameteriv =
// gl->glGetFramebufferParameterivEXTFn;
// functions->fNamedCopyBufferSubData = gl->glNamedCopyBufferSubDataEXTFn;
// functions->fVertexArrayVertexOffset = gl->glVertexArrayVertexOffsetEXTFn;
// functions->fVertexArrayColorOffset = gl->glVertexArrayColorOffsetEXTFn;
// functions->fVertexArrayEdgeFlagOffset =
// gl->glVertexArrayEdgeFlagOffsetEXTFn;
// functions->fVertexArrayIndexOffset = gl->glVertexArrayIndexOffsetEXTFn;
// functions->fVertexArrayNormalOffset = gl->glVertexArrayNormalOffsetEXTFn;
// functions->fVertexArrayTexCoordOffset =
// gl->glVertexArrayTexCoordOffsetEXTFn;
// functions->fVertexArrayMultiTexCoordOffset =
// gl->glVertexArrayMultiTexCoordOffsetEXTFn;
// functions->fVertexArrayFogCoordOffset =
// gl->glVertexArrayFogCoordOffsetEXTFn;
// functions->fVertexArraySecondaryColorOffset =
// gl->glVertexArraySecondaryColorOffsetEXTFn;
// functions->fVertexArrayVertexAttribOffset =
// gl->glVertexArrayVertexAttribOffsetEXTFn;
// functions->fVertexArrayVertexAttribIOffset =
// gl->glVertexArrayVertexAttribIOffsetEXTFn;
// functions->fEnableVertexArray = gl->glEnableVertexArrayEXTFn;
// functions->fDisableVertexArray = gl->glDisableVertexArrayEXTFn;
// functions->fEnableVertexArrayAttrib = gl->glEnableVertexArrayAttribEXTFn;
// functions->fDisableVertexArrayAttrib = gl->glDisableVertexArrayAttribEXTFn;
// functions->fGetVertexArrayIntegerv = gl->glGetVertexArrayIntegervEXTFn;
// functions->fGetVertexArrayPointerv = gl->glGetVertexArrayPointervEXTFn;
// functions->fGetVertexArrayIntegeri_v = gl->glGetVertexArrayIntegeri_vEXTFn;
// functions->fGetVertexArrayPointeri_v = gl->glGetVertexArrayPointeri_vEXTFn;
// functions->fMapNamedBufferRange = gl->glMapNamedBufferRangeEXTFn;
// functions->fFlushMappedNamedBufferRange =
// gl->glFlushMappedNamedBufferRangeEXTFn;
// functions->fTextureBuffer = gl->glTextureBufferEXTFn;
// 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) {
functions->fDebugMessageControl = gl->glDebugMessageControlFn;
functions->fDebugMessageInsert = gl->glDebugMessageInsertFn;
functions->fDebugMessageCallback = gl->glDebugMessageCallbackFn;
functions->fGetDebugMessageLog = gl->glGetDebugMessageLogFn;
functions->fPushDebugGroup = gl->glPushDebugGroupFn;
functions->fPopDebugGroup = gl->glPopDebugGroupFn;
functions->fObjectLabel = gl->glObjectLabelFn;
} else {
extensions.remove("GL_KHR_debug");
}
// GL_EXT_window_rectangles
functions->fWindowRectangles = gl->glWindowRectanglesEXTFn;
// GL_QCOM_tiled_rendering
functions->fStartTiling = gl->glStartTilingQCOMFn;
functions->fEndTiling = gl->glEndTilingQCOMFn;
// EGL_KHR_image / EGL_KHR_image_base
// functions->fCreateImage = nullptr;
// functions->fDestroyImage = nullptr;
functions->fFenceSync = gl->glFenceSyncFn;
functions->fIsSync = gl->glIsSyncFn;
functions->fClientWaitSync = gl->glClientWaitSyncFn;
functions->fWaitSync = gl->glWaitSyncFn;
functions->fDeleteSync = gl->glDeleteSyncFn;
if (!gl->glFenceSyncFn) {
// NOTE: Skia uses the same function pointers without APPLE suffix
if (extensions.has("GL_APPLE_sync")) {
functions->fFenceSync = gl->glFenceSyncAPPLEFn;
functions->fIsSync = gl->glIsSyncAPPLEFn;
functions->fClientWaitSync = gl->glClientWaitSyncAPPLEFn;
functions->fWaitSync = gl->glWaitSyncAPPLEFn;
functions->fDeleteSync = gl->glDeleteSyncAPPLEFn;
} else if (g_driver_egl.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;
}
} else if (use_version_es2) {
// We have gl sync, but want to Skia use ES2 that doesn't have fences.
// To provide Skia with ways of sync to prevent it calling glFinish we set
// GL_APPLE_sync support.
extensions.add("GL_APPLE_sync");
}
functions->fGetInternalformativ = gl->glGetInternalformativFn;
interface->fStandard = standard;
interface->fExtensions.swap(&extensions);
sk_sp<GrGLInterface> returned(interface);
return returned;
}
} // namespace init
} // namespace gl